1
The following changes since commit b11365867568ba954de667a0bfe0945b8f78d6bd:
1
The following changes since commit f1d33f55c47dfdaf8daacd618588ad3ae4c452d1:
2
2
3
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20170706' into staging (2017-07-06 11:42:59 +0100)
3
Merge tag 'pull-testing-gdbstub-plugins-gitdm-061022-3' of https://github.com/stsquad/qemu into staging (2022-10-06 07:11:56 -0400)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
7
6
8
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
9
8
10
for you to fetch changes up to 7d982302db173616d011e07ee43be3b0aae872b1:
9
for you to fetch changes up to a7ca2eb488ff149c898f43abe103f8bd8e3ca3c4:
11
10
12
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-07-07' into queue-block (2017-07-07 18:11:41 +0200)
11
file-posix: Remove unused s->discard_zeroes (2022-10-07 12:11:41 +0200)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
16
Block layer patches
14
Block layer patches
17
15
16
- job: replace AioContext lock with job_mutex
17
- Fixes to make coroutine_fn annotations more accurate
18
- QAPI schema: Fix incorrect example
19
- Code cleanup
20
18
----------------------------------------------------------------
21
----------------------------------------------------------------
19
Daniel P. Berrange (26):
22
Alberto Faria (1):
20
qemu-img: drop -e and -6 options from the 'create' & 'convert' commands
23
coroutine: Drop coroutine_fn annotation from qemu_coroutine_self()
21
block: expose crypto option names / defs to other drivers
22
block: add ability to set a prefix for opt names
23
qcow: document another weakness of qcow AES encryption
24
qcow: require image size to be > 1 for new images
25
iotests: skip 042 with qcow which dosn't support zero sized images
26
iotests: skip 048 with qcow which doesn't support resize
27
block: deprecate "encryption=on" in favor of "encrypt.format=aes"
28
qcow: make encrypt_sectors encrypt in place
29
qcow: convert QCow to use QCryptoBlock for encryption
30
qcow2: make qcow2_encrypt_sectors encrypt in place
31
qcow2: convert QCow2 to use QCryptoBlock for encryption
32
qcow2: extend specification to cover LUKS encryption
33
qcow2: add support for LUKS encryption format
34
qcow2: add iotests to cover LUKS encryption support
35
iotests: enable tests 134 and 158 to work with qcow (v1)
36
block: rip out all traces of password prompting
37
block: remove all encryption handling APIs
38
block: pass option prefix down to crypto layer
39
qcow2: report encryption specific image information
40
docs: document encryption options for qcow, qcow2 and luks
41
iotests: skip 159 & 170 with luks format
42
iotests: fix remainining tests to work with LUKS
43
iotests: reduce PBKDF iterations when testing LUKS
44
iotests: add more LUKS hash combination tests
45
iotests: chown LUKS device before qemu-io launches
46
24
47
Eric Blake (26):
25
Emanuele Giuseppe Esposito (20):
48
qemu-io: Don't die on second open
26
job.c: make job_mutex and job_lock/unlock() public
49
block: Guarantee that *file is set on bdrv_get_block_status()
27
job.h: categorize fields in struct Job
50
block: Simplify use of BDRV_BLOCK_RAW
28
job.c: API functions not used outside should be static
51
blkdebug: Support .bdrv_co_get_block_status
29
aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED
52
blockjob: Track job ratelimits via bytes, not sectors
30
job.c: add job_lock/unlock while keeping job.h intact
53
trace: Show blockjob actions via bytes, not sectors
31
job: move and update comments from blockjob.c
54
stream: Switch stream_populate() to byte-based
32
blockjob: introduce block_job _locked() APIs
55
stream: Drop reached_end for stream_complete()
33
jobs: add job lock in find_* functions
56
stream: Switch stream_run() to byte-based
34
jobs: use job locks also in the unit tests
57
commit: Switch commit_populate() to byte-based
35
block/mirror.c: use of job helpers in drivers
58
commit: Switch commit_run() to byte-based
36
jobs: group together API calls under the same job lock
59
mirror: Switch MirrorBlockJob to byte-based
37
jobs: protect job.aio_context with BQL and job_mutex
60
mirror: Switch mirror_do_zero_or_discard() to byte-based
38
blockjob.h: categorize fields in struct BlockJob
61
mirror: Update signature of mirror_clip_sectors()
39
blockjob: rename notifier callbacks as _locked
62
mirror: Switch mirror_cow_align() to byte-based
40
blockjob: protect iostatus field in BlockJob struct
63
mirror: Switch mirror_do_read() to byte-based
41
job.h: categorize JobDriver callbacks that need the AioContext lock
64
mirror: Switch mirror_iteration() to byte-based
42
job.c: enable job lock/unlock and remove Aiocontext locks
65
block: Drop unused bdrv_round_sectors_to_clusters()
43
block_job_query: remove atomic read
66
backup: Switch BackupBlockJob to byte-based
44
blockjob: remove unused functions
67
backup: Switch block_backup.h to byte-based
45
job: remove unused functions
68
backup: Switch backup_do_cow() to byte-based
69
backup: Switch backup_run() to byte-based
70
block: Make bdrv_is_allocated() byte-based
71
block: Minimize raw use of bds->total_sectors
72
block: Make bdrv_is_allocated_above() byte-based
73
tests: Avoid non-portable 'echo -ARG'
74
46
75
Hervé Poussineau (13):
47
Kevin Wolf (2):
76
vvfat: fix qemu-img map and qemu-img convert
48
quorum: Remove unnecessary forward declaration
77
vvfat: replace tabs by 8 spaces
49
file-posix: Remove unused s->discard_zeroes
78
vvfat: fix typos
79
vvfat: rename useless enumeration values
80
vvfat: introduce offset_to_bootsector, offset_to_fat and offset_to_root_dir
81
vvfat: fix field names in FAT12/FAT16 and FAT32 boot sectors
82
vvfat: always create . and .. entries at first and in that order
83
vvfat: correctly create long names for non-ASCII filenames
84
vvfat: correctly create base short names for non-ASCII filenames
85
vvfat: correctly generate numeric-tail of short file names
86
vvfat: limit number of entries in root directory in FAT12/FAT16
87
vvfat: handle KANJI lead byte 0xe5
88
vvfat: change OEM name to 'MSWIN4.1'
89
50
90
Kevin Wolf (1):
51
Marc-André Lureau (3):
91
Merge remote-tracking branch 'mreitz/tags/pull-block-2017-07-07' into queue-block
52
9p: add missing coroutine_fn annotations
53
migration: add missing coroutine_fn annotations
54
test-coroutine: add missing coroutine_fn annotations
92
55
93
Max Reitz (3):
56
Markus Armbruster (1):
94
iotests: 181 does not work for all formats
57
Revert "qapi: fix examples of blockdev-add with qcow2"
95
iotests: Use absolute paths for executables
96
iotests: Add test for colon handling
97
58
98
Thomas Huth (1):
59
Paolo Bonzini (23):
99
blockdev: Print a warning for legacy drive options that belong to -device
60
block/nvme: separate nvme_get_free_req cases for coroutine/non-coroutine context
61
block: add missing coroutine_fn annotations
62
qcow2: remove incorrect coroutine_fn annotations
63
nbd: remove incorrect coroutine_fn annotations
64
coroutine: remove incorrect coroutine_fn annotations
65
blkverify: add missing coroutine_fn annotations
66
file-posix: add missing coroutine_fn annotations
67
iscsi: add missing coroutine_fn annotations
68
nbd: add missing coroutine_fn annotations
69
nfs: add missing coroutine_fn annotations
70
nvme: add missing coroutine_fn annotations
71
parallels: add missing coroutine_fn annotations
72
qcow2: add missing coroutine_fn annotations
73
copy-before-write: add missing coroutine_fn annotations
74
curl: add missing coroutine_fn annotations
75
qed: add missing coroutine_fn annotations
76
quorum: add missing coroutine_fn annotations
77
throttle: add missing coroutine_fn annotations
78
vmdk: add missing coroutine_fn annotations
79
job: add missing coroutine_fn annotations
80
coroutine-lock: add missing coroutine_fn annotations
81
raw-format: add missing coroutine_fn annotations
82
job: detect change of aiocontext within job coroutine
100
83
101
Vladimir Sementsov-Ogievskiy (30):
84
qapi/block-core.json | 10 +-
102
specs/qcow2: fix bitmap granularity qemu-specific note
85
block/qcow2.h | 19 +-
103
specs/qcow2: do not use wording 'bitmap header'
86
hw/9pfs/9p.h | 9 +-
104
hbitmap: improve dirty iter
87
include/block/aio-wait.h | 17 +-
105
tests: add hbitmap iter test
88
include/block/blockjob.h | 59 +++-
106
block: fix bdrv_dirty_bitmap_granularity signature
89
include/block/nbd.h | 2 +-
107
block/dirty-bitmap: add deserialize_ones func
90
include/qemu/coroutine.h | 4 +-
108
qcow2-refcount: rename inc_refcounts() and make it public
91
include/qemu/job.h | 306 +++++++++++++-----
109
qcow2: add bitmaps extension
92
block.c | 24 +-
110
block/dirty-bitmap: fix comment for BlockDirtyBitmap.disabled field
93
block/blkverify.c | 2 +-
111
block/dirty-bitmap: add readonly field to BdrvDirtyBitmap
94
block/block-backend.c | 10 +-
112
qcow2: autoloading dirty bitmaps
95
block/copy-before-write.c | 9 +-
113
block: refactor bdrv_reopen_commit
96
block/curl.c | 2 +-
114
block: new bdrv_reopen_bitmaps_rw interface
97
block/file-posix.c | 11 +-
115
qcow2: support .bdrv_reopen_bitmaps_rw
98
block/io.c | 22 +-
116
block/dirty-bitmap: add autoload field to BdrvDirtyBitmap
99
block/iscsi.c | 3 +-
117
block: bdrv_close: release bitmaps after drv->bdrv_close
100
block/mirror.c | 19 +-
118
block: introduce persistent dirty bitmaps
101
block/nbd.c | 11 +-
119
block/dirty-bitmap: add bdrv_dirty_bitmap_next()
102
block/nfs.c | 2 +-
120
qcow2: add persistent dirty bitmaps support
103
block/nvme.c | 54 ++--
121
qcow2: store bitmaps on reopening image as read-only
104
block/parallels.c | 5 +-
122
block: add bdrv_can_store_new_dirty_bitmap
105
block/qcow2-cluster.c | 21 +-
123
qcow2: add .bdrv_can_store_new_dirty_bitmap
106
block/qcow2-refcount.c | 6 +-
124
qmp: add persistent flag to block-dirty-bitmap-add
107
block/qcow2.c | 5 +-
125
qmp: add autoload parameter to block-dirty-bitmap-add
108
block/qed.c | 4 +-
126
qmp: add x-debug-block-dirty-bitmap-sha256
109
block/quorum.c | 38 +--
127
iotests: test qcow2 persistent dirty bitmap
110
block/raw-format.c | 3 +-
128
block/dirty-bitmap: add bdrv_remove_persistent_dirty_bitmap
111
block/replication.c | 3 +
129
qcow2: add .bdrv_remove_persistent_dirty_bitmap
112
block/throttle.c | 2 +-
130
qmp: block-dirty-bitmap-remove: remove persistent
113
block/vmdk.c | 22 +-
131
block: release persistent bitmaps on inactivate
114
blockdev.c | 129 ++++----
115
blockjob.c | 132 ++++----
116
job-qmp.c | 92 +++---
117
job.c | 674 +++++++++++++++++++++++++--------------
118
migration/migration.c | 3 +-
119
monitor/qmp-cmds.c | 7 +-
120
qemu-img.c | 17 +-
121
tests/unit/test-bdrv-drain.c | 80 +++--
122
tests/unit/test-block-iothread.c | 8 +-
123
tests/unit/test-blockjob-txn.c | 24 +-
124
tests/unit/test-blockjob.c | 136 ++++----
125
tests/unit/test-coroutine.c | 2 +-
126
util/qemu-coroutine-lock.c | 14 +-
127
util/qemu-coroutine.c | 2 +-
128
44 files changed, 1237 insertions(+), 787 deletions(-)
132
129
133
sochin.jiang (1):
134
mirror: Fix inconsistent backing AioContext for after mirroring
135
130
136
block.c | 143 +--
137
block/Makefile.objs | 2 +-
138
block/backup.c | 128 +--
139
block/blkdebug.c | 11 +
140
block/commit.c | 56 +-
141
block/crypto.c | 97 +-
142
block/crypto.h | 101 ++
143
block/dirty-bitmap.c | 154 ++-
144
block/io.c | 110 +-
145
block/mirror.c | 310 ++---
146
block/qapi.c | 2 +-
147
block/qcow.c | 269 ++---
148
block/qcow2-bitmap.c | 1481 ++++++++++++++++++++++++
149
block/qcow2-cluster.c | 66 +-
150
block/qcow2-refcount.c | 69 +-
151
block/qcow2.c | 653 +++++++++--
152
block/qcow2.h | 60 +-
153
block/raw-format.c | 2 +-
154
block/replication.c | 29 +-
155
block/stream.c | 37 +-
156
block/trace-events | 14 +-
157
block/vpc.c | 2 +-
158
block/vvfat.c | 2336 ++++++++++++++++++++------------------
159
blockdev.c | 124 +-
160
crypto/block-luks.c | 8 +-
161
crypto/block-qcow.c | 8 +-
162
crypto/block.c | 6 +-
163
crypto/blockpriv.h | 2 +
164
docs/interop/qcow2.txt | 111 +-
165
hmp-commands.hx | 2 +
166
hmp.c | 31 -
167
include/block/block.h | 22 +-
168
include/block/block_backup.h | 11 +-
169
include/block/block_int.h | 17 +-
170
include/block/dirty-bitmap.h | 22 +-
171
include/crypto/block.h | 6 +-
172
include/monitor/monitor.h | 7 -
173
include/qapi/error.h | 1 -
174
include/qemu/hbitmap.h | 49 +-
175
include/qemu/osdep.h | 2 -
176
include/qemu/ratelimit.h | 3 +-
177
migration/block.c | 16 +-
178
monitor.c | 68 --
179
qapi-schema.json | 10 +-
180
qapi/block-core.json | 172 ++-
181
qapi/common.json | 5 +-
182
qemu-doc.texi | 123 +-
183
qemu-img.c | 76 +-
184
qemu-img.texi | 19 +-
185
qemu-io-cmds.c | 70 +-
186
qemu-io.c | 27 +-
187
qemu-options.hx | 13 +-
188
qmp.c | 12 +-
189
tests/Makefile.include | 2 +-
190
tests/multiboot/run_test.sh | 10 +-
191
tests/qemu-iotests/033 | 12 +-
192
tests/qemu-iotests/042 | 2 +-
193
tests/qemu-iotests/048 | 2 +-
194
tests/qemu-iotests/049 | 2 +-
195
tests/qemu-iotests/049.out | 102 +-
196
tests/qemu-iotests/051 | 7 +-
197
tests/qemu-iotests/060.out | 1 +
198
tests/qemu-iotests/068 | 2 +-
199
tests/qemu-iotests/082.out | 284 ++++-
200
tests/qemu-iotests/085.out | 38 +-
201
tests/qemu-iotests/087 | 39 +-
202
tests/qemu-iotests/087.out | 16 +-
203
tests/qemu-iotests/114.out | 5 +-
204
tests/qemu-iotests/120 | 1 +
205
tests/qemu-iotests/126 | 105 ++
206
tests/qemu-iotests/126.out | 23 +
207
tests/qemu-iotests/134 | 20 +-
208
tests/qemu-iotests/134.out | 10 +-
209
tests/qemu-iotests/140 | 9 +-
210
tests/qemu-iotests/142 | 48 +-
211
tests/qemu-iotests/144.out | 4 +-
212
tests/qemu-iotests/145 | 19 +-
213
tests/qemu-iotests/149 | 25 +-
214
tests/qemu-iotests/149.out | 1002 +++++++++++-----
215
tests/qemu-iotests/153.out | 6 +
216
tests/qemu-iotests/157 | 17 +-
217
tests/qemu-iotests/157.out | 16 +-
218
tests/qemu-iotests/158 | 21 +-
219
tests/qemu-iotests/158.out | 14 +-
220
tests/qemu-iotests/159 | 1 +
221
tests/qemu-iotests/165 | 105 ++
222
tests/qemu-iotests/165.out | 5 +
223
tests/qemu-iotests/170 | 1 +
224
tests/qemu-iotests/171 | 14 +-
225
tests/qemu-iotests/174 | 2 +-
226
tests/qemu-iotests/177 | 3 +
227
tests/qemu-iotests/177.out | 5 +
228
tests/qemu-iotests/181 | 23 +-
229
tests/qemu-iotests/185.out | 8 +-
230
tests/qemu-iotests/188 | 76 ++
231
tests/qemu-iotests/188.out | 18 +
232
tests/qemu-iotests/189 | 86 ++
233
tests/qemu-iotests/189.out | 26 +
234
tests/qemu-iotests/check | 18 +-
235
tests/qemu-iotests/common | 10 +-
236
tests/qemu-iotests/common.config | 11 +
237
tests/qemu-iotests/common.filter | 3 +-
238
tests/qemu-iotests/common.qemu | 9 +-
239
tests/qemu-iotests/common.rc | 3 +
240
tests/qemu-iotests/group | 4 +
241
tests/rocker/all | 10 +-
242
tests/tcg/cris/Makefile | 8 +-
243
tests/test-crypto-block.c | 8 +-
244
tests/test-hbitmap.c | 19 +
245
util/hbitmap.c | 51 +-
246
util/oslib-posix.c | 66 --
247
util/oslib-win32.c | 24 -
248
112 files changed, 6714 insertions(+), 2942 deletions(-)
249
create mode 100644 block/crypto.h
250
create mode 100644 block/qcow2-bitmap.c
251
create mode 100755 tests/qemu-iotests/126
252
create mode 100644 tests/qemu-iotests/126.out
253
create mode 100755 tests/qemu-iotests/165
254
create mode 100644 tests/qemu-iotests/165.out
255
create mode 100755 tests/qemu-iotests/188
256
create mode 100644 tests/qemu-iotests/188.out
257
create mode 100755 tests/qemu-iotests/189
258
create mode 100644 tests/qemu-iotests/189.out
259
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Markus Armbruster <armbru@redhat.com>
2
2
3
Remove persistent bitmap from the storage on block-dirty-bitmap-remove.
3
This reverts commit b6522938327141235b97ab38e40c6c4512587373.
4
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Kevin Wolf NAKed this patch, because:
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
7
Reviewed-by: John Snow <jsnow@redhat.com>
7
'file' is a required member (defined in BlockdevOptionsGenericFormat),
8
Message-id: 20170628120530.31251-30-vsementsov@virtuozzo.com
8
removing it makes the example invalid. 'data-file' is only an additional
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
optional member to be used for external data files (i.e. when the guest
10
data is kept separate from the metadata in the .qcow2 file).
11
12
However, it had already been merged then. Revert.
13
14
Signed-off-by: Markus Armbruster <armbru@redhat.com>
15
Message-Id: <20220930171908.846769-1-armbru@redhat.com>
16
Reviewed-by: Victor Toso <victortoso@redhat.com>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
19
---
11
blockdev.c | 10 ++++++++++
20
qapi/block-core.json | 10 +++++-----
12
qapi/block-core.json | 3 ++-
21
1 file changed, 5 insertions(+), 5 deletions(-)
13
2 files changed, 12 insertions(+), 1 deletion(-)
14
22
15
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
18
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
20
{
21
BlockDriverState *bs;
22
BdrvDirtyBitmap *bitmap;
23
+ Error *local_err = NULL;
24
25
bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
26
if (!bitmap || !bs) {
27
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
28
name);
29
return;
30
}
31
+
32
+ if (bdrv_dirty_bitmap_get_persistance(bitmap)) {
33
+ bdrv_remove_persistent_dirty_bitmap(bs, name, &local_err);
34
+ if (local_err != NULL) {
35
+ error_propagate(errp, local_err);
36
+ return;
37
+ }
38
+ }
39
+
40
bdrv_dirty_bitmap_make_anon(bitmap);
41
bdrv_release_dirty_bitmap(bs, bitmap);
42
}
43
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
44
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
45
--- a/qapi/block-core.json
25
--- a/qapi/block-core.json
46
+++ b/qapi/block-core.json
26
+++ b/qapi/block-core.json
47
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
48
# @block-dirty-bitmap-remove:
28
# -> { "execute": "blockdev-add",
29
# "arguments": { "driver": "qcow2",
30
# "node-name": "node1534",
31
-# "data-file": { "driver": "file",
32
-# "filename": "hd1.qcow2" },
33
+# "file": { "driver": "file",
34
+# "filename": "hd1.qcow2" },
35
# "backing": null } }
49
#
36
#
50
# Stop write tracking and remove the dirty bitmap that was created
37
# <- { "return": {} }
51
-# with block-dirty-bitmap-add.
38
@@ -XXX,XX +XXX,XX @@
52
+# with block-dirty-bitmap-add. If the bitmap is persistent, remove it from its
39
# "arguments": {
53
+# storage too.
40
# "driver": "qcow2",
54
#
41
# "node-name": "test1",
55
# Returns: nothing on success
42
-# "data-file": {
56
# If @node is not a valid block device or node, DeviceNotFound
43
+# "file": {
44
# "driver": "file",
45
# "filename": "test.qcow2"
46
# }
47
@@ -XXX,XX +XXX,XX @@
48
# "cache": {
49
# "direct": true
50
# },
51
-# "data-file": {
52
+# "file": {
53
# "driver": "file",
54
# "filename": "/tmp/test.qcow2"
55
# },
56
@@ -XXX,XX +XXX,XX @@
57
# "arguments": {
58
# "driver": "qcow2",
59
# "node-name": "node0",
60
-# "data-file": {
61
+# "file": {
62
# "driver": "file",
63
# "filename": "test.qcow2"
64
# }
57
--
65
--
58
1.8.3.1
66
2.37.3
59
60
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
MODE_FAKED and MODE_RENAMED are not and were never used.
3
qemu_coroutine_self() can be called from outside coroutine context,
4
returning the leader coroutine, and several such invocations currently
5
exist (mostly in qcow2 tracing calls).
4
6
5
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
7
Signed-off-by: Alberto Faria <afaria@redhat.com>
8
Message-Id: <20221005175209.975797-1-afaria@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
block/vvfat.c | 13 ++++++++-----
13
include/qemu/coroutine.h | 2 +-
9
1 file changed, 8 insertions(+), 5 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
15
11
diff --git a/block/vvfat.c b/block/vvfat.c
16
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/block/vvfat.c
18
--- a/include/qemu/coroutine.h
14
+++ b/block/vvfat.c
19
+++ b/include/qemu/coroutine.h
15
@@ -XXX,XX +XXX,XX @@ typedef struct mapping_t {
20
@@ -XXX,XX +XXX,XX @@ AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co);
16
union {
21
/**
17
/* offset is
22
* Get the currently executing coroutine
18
* - the offset in the file (in clusters) for a file, or
23
*/
19
- * - the next cluster of the directory for a directory, and
24
-Coroutine *coroutine_fn qemu_coroutine_self(void);
20
- * - the address of the buffer for a faked entry
25
+Coroutine *qemu_coroutine_self(void);
21
+ * - the next cluster of the directory for a directory
26
22
*/
27
/**
23
struct {
28
* Return whether or not currently inside a coroutine
24
uint32_t offset;
25
@@ -XXX,XX +XXX,XX @@ typedef struct mapping_t {
26
/* path contains the full path, i.e. it always starts with s->path */
27
char* path;
28
29
- enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
30
- MODE_DIRECTORY = 4, MODE_FAKED = 8,
31
- MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
32
+ enum {
33
+ MODE_UNDEFINED = 0,
34
+ MODE_NORMAL = 1,
35
+ MODE_MODIFIED = 2,
36
+ MODE_DIRECTORY = 4,
37
+ MODE_DELETED = 8,
38
+ } mode;
39
int read_only;
40
} mapping_t;
41
42
--
29
--
43
1.8.3.1
30
2.37.3
44
45
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Make dirty iter resistant to resetting bits in corresponding HBitmap.
3
nvme_get_free_req has very difference semantics when called in
4
coroutine context (where it waits) and in non-coroutine context
5
(where it doesn't). Split the two cases to make it clear what
6
is being requested.
4
7
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Cc: qemu-block@nongnu.org
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-id: 20170628120530.31251-4-vsementsov@virtuozzo.com
11
Message-Id: <20220922084924.201610-2-pbonzini@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
[kwolf: Fixed up coding style]
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
include/qemu/hbitmap.h | 26 ++++----------------------
16
block/nvme.c | 48 ++++++++++++++++++++++++++++--------------------
12
util/hbitmap.c | 23 ++++++++++++++++++++++-
17
1 file changed, 28 insertions(+), 20 deletions(-)
13
2 files changed, 26 insertions(+), 23 deletions(-)
14
18
15
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
19
diff --git a/block/nvme.c b/block/nvme.c
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/include/qemu/hbitmap.h
21
--- a/block/nvme.c
18
+++ b/include/qemu/hbitmap.h
22
+++ b/block/nvme.c
19
@@ -XXX,XX +XXX,XX @@ void hbitmap_free(HBitmap *hb);
23
@@ -XXX,XX +XXX,XX @@ static void nvme_kick(NVMeQueuePair *q)
20
* the lowest-numbered bit that is set in @hb, starting at @first.
24
q->need_kick = 0;
21
*
25
}
22
* Concurrent setting of bits is acceptable, and will at worst cause the
26
23
- * iteration to miss some of those bits. Resetting bits before the current
27
-/* Find a free request element if any, otherwise:
24
- * position of the iterator is also okay. However, concurrent resetting of
28
- * a) if in coroutine context, try to wait for one to become available;
25
- * bits can lead to unexpected behavior if the iterator has not yet reached
29
- * b) if not in coroutine, return NULL;
26
- * those bits.
30
- */
27
+ * iteration to miss some of those bits.
31
-static NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
28
+ *
32
+static NVMeRequest *nvme_get_free_req_nofail_locked(NVMeQueuePair *q)
29
+ * The concurrent resetting of bits is OK.
33
{
30
*/
34
NVMeRequest *req;
31
void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first);
35
32
36
- qemu_mutex_lock(&q->lock);
33
@@ -XXX,XX +XXX,XX @@ void hbitmap_free_meta(HBitmap *hb);
34
* Return the next bit that is set in @hbi's associated HBitmap,
35
* or -1 if all remaining bits are zero.
36
*/
37
-static inline int64_t hbitmap_iter_next(HBitmapIter *hbi)
38
-{
39
- unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1];
40
- int64_t item;
41
-
37
-
42
- if (cur == 0) {
38
- while (q->free_req_head == -1) {
43
- cur = hbitmap_iter_skip_words(hbi);
39
- if (qemu_in_coroutine()) {
44
- if (cur == 0) {
40
- trace_nvme_free_req_queue_wait(q->s, q->index);
45
- return -1;
41
- qemu_co_queue_wait(&q->free_req_queue, &q->lock);
42
- } else {
43
- qemu_mutex_unlock(&q->lock);
44
- return NULL;
46
- }
45
- }
47
- }
46
- }
48
-
47
-
49
- /* The next call will resume work from the next bit. */
48
req = &q->reqs[q->free_req_head];
50
- hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1);
49
q->free_req_head = req->free_req_next;
51
- item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur);
50
req->free_req_next = -1;
52
-
51
-
53
- return item << hbi->granularity;
52
- qemu_mutex_unlock(&q->lock);
54
-}
53
return req;
55
+int64_t hbitmap_iter_next(HBitmapIter *hbi);
56
57
/**
58
* hbitmap_iter_next_word:
59
diff --git a/util/hbitmap.c b/util/hbitmap.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/util/hbitmap.c
62
+++ b/util/hbitmap.c
63
@@ -XXX,XX +XXX,XX @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi)
64
65
unsigned long cur;
66
do {
67
- cur = hbi->cur[--i];
68
+ i--;
69
pos >>= BITS_PER_LEVEL;
70
+ cur = hbi->cur[i] & hb->levels[i][pos];
71
} while (cur == 0);
72
73
/* Check for end of iteration. We always use fewer than BITS_PER_LONG
74
@@ -XXX,XX +XXX,XX @@ unsigned long hbitmap_iter_skip_words(HBitmapIter *hbi)
75
return cur;
76
}
54
}
77
55
78
+int64_t hbitmap_iter_next(HBitmapIter *hbi)
56
+/* Return a free request element if any, otherwise return NULL. */
57
+static NVMeRequest *nvme_get_free_req_nowait(NVMeQueuePair *q)
79
+{
58
+{
80
+ unsigned long cur = hbi->cur[HBITMAP_LEVELS - 1] &
59
+ QEMU_LOCK_GUARD(&q->lock);
81
+ hbi->hb->levels[HBITMAP_LEVELS - 1][hbi->pos];
60
+ if (q->free_req_head == -1) {
82
+ int64_t item;
61
+ return NULL;
62
+ }
63
+ return nvme_get_free_req_nofail_locked(q);
64
+}
83
+
65
+
84
+ if (cur == 0) {
66
+/*
85
+ cur = hbitmap_iter_skip_words(hbi);
67
+ * Wait for a free request to become available if necessary, then
86
+ if (cur == 0) {
68
+ * return it.
87
+ return -1;
69
+ */
88
+ }
70
+static coroutine_fn NVMeRequest *nvme_get_free_req(NVMeQueuePair *q)
71
+{
72
+ QEMU_LOCK_GUARD(&q->lock);
73
+
74
+ while (q->free_req_head == -1) {
75
+ trace_nvme_free_req_queue_wait(q->s, q->index);
76
+ qemu_co_queue_wait(&q->free_req_queue, &q->lock);
89
+ }
77
+ }
90
+
78
+
91
+ /* The next call will resume work from the next bit. */
79
+ return nvme_get_free_req_nofail_locked(q);
92
+ hbi->cur[HBITMAP_LEVELS - 1] = cur & (cur - 1);
93
+ item = ((uint64_t)hbi->pos << BITS_PER_LEVEL) + ctzl(cur);
94
+
95
+ return item << hbi->granularity;
96
+}
80
+}
97
+
81
+
98
void hbitmap_iter_init(HBitmapIter *hbi, const HBitmap *hb, uint64_t first)
82
/* With q->lock */
83
static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req)
99
{
84
{
100
unsigned i, bit;
85
@@ -XXX,XX +XXX,XX @@ static int nvme_admin_cmd_sync(BlockDriverState *bs, NvmeCmd *cmd)
86
AioContext *aio_context = bdrv_get_aio_context(bs);
87
NVMeRequest *req;
88
int ret = -EINPROGRESS;
89
- req = nvme_get_free_req(q);
90
+ req = nvme_get_free_req_nowait(q);
91
if (!req) {
92
return -EBUSY;
93
}
101
--
94
--
102
1.8.3.1
95
2.37.3
103
104
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We should release them here to reload on invalidate cache.
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
4
6
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20220922084924.201610-3-pbonzini@redhat.com>
7
Message-id: 20170628120530.31251-31-vsementsov@virtuozzo.com
9
[kwolf: Fixed up coding style]
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
12
---
10
block.c | 4 ++++
13
block.c | 7 ++++---
11
block/dirty-bitmap.c | 29 +++++++++++++++++++++++------
14
block/block-backend.c | 10 +++++-----
12
include/block/dirty-bitmap.h | 1 +
15
block/io.c | 22 +++++++++++-----------
13
3 files changed, 28 insertions(+), 6 deletions(-)
16
3 files changed, 20 insertions(+), 19 deletions(-)
14
17
15
diff --git a/block.c b/block.c
18
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
20
--- a/block.c
18
+++ b/block.c
21
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
22
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
20
}
23
* Helper function for bdrv_create_file_fallback(): Zero the first
21
}
24
* sector to remove any potentially pre-existing image header.
22
25
*/
23
+ /* At this point persistent bitmaps should be already stored by the format
26
-static int create_file_fallback_zero_first_sector(BlockBackend *blk,
24
+ * driver */
27
- int64_t current_size,
25
+ bdrv_release_persistent_dirty_bitmaps(bs);
28
- Error **errp)
26
+
29
+static int coroutine_fn
27
return 0;
30
+create_file_fallback_zero_first_sector(BlockBackend *blk,
31
+ int64_t current_size,
32
+ Error **errp)
33
{
34
int64_t bytes_to_clear;
35
int ret;
36
diff --git a/block/block-backend.c b/block/block-backend.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/block-backend.c
39
+++ b/block/block-backend.c
40
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
41
return &acb->common;
28
}
42
}
29
43
30
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
44
-static void blk_aio_read_entry(void *opaque)
45
+static void coroutine_fn blk_aio_read_entry(void *opaque)
46
{
47
BlkAioEmAIOCB *acb = opaque;
48
BlkRwCo *rwco = &acb->rwco;
49
@@ -XXX,XX +XXX,XX @@ static void blk_aio_read_entry(void *opaque)
50
blk_aio_complete(acb);
51
}
52
53
-static void blk_aio_write_entry(void *opaque)
54
+static void coroutine_fn blk_aio_write_entry(void *opaque)
55
{
56
BlkAioEmAIOCB *acb = opaque;
57
BlkRwCo *rwco = &acb->rwco;
58
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
59
return ret;
60
}
61
62
-static void blk_aio_ioctl_entry(void *opaque)
63
+static void coroutine_fn blk_aio_ioctl_entry(void *opaque)
64
{
65
BlkAioEmAIOCB *acb = opaque;
66
BlkRwCo *rwco = &acb->rwco;
67
@@ -XXX,XX +XXX,XX @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
68
return bdrv_co_pdiscard(blk->root, offset, bytes);
69
}
70
71
-static void blk_aio_pdiscard_entry(void *opaque)
72
+static void coroutine_fn blk_aio_pdiscard_entry(void *opaque)
73
{
74
BlkAioEmAIOCB *acb = opaque;
75
BlkRwCo *rwco = &acb->rwco;
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
77
return bdrv_co_flush(blk_bs(blk));
78
}
79
80
-static void blk_aio_flush_entry(void *opaque)
81
+static void coroutine_fn blk_aio_flush_entry(void *opaque)
82
{
83
BlkAioEmAIOCB *acb = opaque;
84
BlkRwCo *rwco = &acb->rwco;
85
diff --git a/block/io.c b/block/io.c
31
index XXXXXXX..XXXXXXX 100644
86
index XXXXXXX..XXXXXXX 100644
32
--- a/block/dirty-bitmap.c
87
--- a/block/io.c
33
+++ b/block/dirty-bitmap.c
88
+++ b/block/io.c
34
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
89
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn tracked_request_end(BdrvTrackedRequest *req)
35
bdrv_dirty_bitmaps_unlock(bs);
90
/**
91
* Add an active request to the tracked requests list
92
*/
93
-static void tracked_request_begin(BdrvTrackedRequest *req,
94
- BlockDriverState *bs,
95
- int64_t offset,
96
- int64_t bytes,
97
- enum BdrvTrackedRequestType type)
98
+static void coroutine_fn tracked_request_begin(BdrvTrackedRequest *req,
99
+ BlockDriverState *bs,
100
+ int64_t offset,
101
+ int64_t bytes,
102
+ enum BdrvTrackedRequestType type)
103
{
104
bdrv_check_request(offset, bytes, &error_abort);
105
106
@@ -XXX,XX +XXX,XX @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
36
}
107
}
37
108
38
+static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap)
109
/* Called with self->bs->reqs_lock held */
39
+{
110
-static BdrvTrackedRequest *
40
+ return !!bdrv_dirty_bitmap_name(bitmap);
111
+static coroutine_fn BdrvTrackedRequest *
41
+}
112
bdrv_find_conflicting_request(BdrvTrackedRequest *self)
42
+
43
/* Called with BQL taken. */
44
-static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs,
45
- BdrvDirtyBitmap *bitmap,
46
- bool only_named)
47
+static void bdrv_do_release_matching_dirty_bitmap(
48
+ BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
49
+ bool (*cond)(BdrvDirtyBitmap *bitmap))
50
{
113
{
51
BdrvDirtyBitmap *bm, *next;
114
BdrvTrackedRequest *req;
52
bdrv_dirty_bitmaps_lock(bs);
115
@@ -XXX,XX +XXX,XX @@ static bool bdrv_init_padding(BlockDriverState *bs,
53
QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
116
return true;
54
- if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) {
117
}
55
+ if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) {
118
56
assert(!bm->active_iterators);
119
-static int bdrv_padding_rmw_read(BdrvChild *child,
57
assert(!bdrv_dirty_bitmap_frozen(bm));
120
- BdrvTrackedRequest *req,
58
assert(!bm->meta);
121
- BdrvRequestPadding *pad,
122
- bool zero_middle)
123
+static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child,
124
+ BdrvTrackedRequest *req,
125
+ BdrvRequestPadding *pad,
126
+ bool zero_middle)
127
{
128
QEMUIOVector local_qiov;
129
BlockDriverState *bs = child->bs;
59
@@ -XXX,XX +XXX,XX @@ out:
130
@@ -XXX,XX +XXX,XX @@ out:
60
/* Called with BQL taken. */
131
return ret;
61
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
132
}
133
134
-int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
135
+int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf)
62
{
136
{
63
- bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false);
137
BlockDriver *drv = bs->drv;
64
+ bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL);
138
CoroutineIOCompletion co = {
65
}
66
67
/**
68
@@ -XXX,XX +XXX,XX @@ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
69
*/
70
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
71
{
72
- bdrv_do_release_matching_dirty_bitmap(bs, NULL, true);
73
+ bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name);
74
+}
75
+
76
+/**
77
+ * Release all persistent dirty bitmaps attached to a BDS (for use in
78
+ * bdrv_inactivate_recurse()).
79
+ * There must not be any frozen bitmaps attached.
80
+ * This function does not remove persistent bitmaps from the storage.
81
+ */
82
+void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs)
83
+{
84
+ bdrv_do_release_matching_dirty_bitmap(bs, NULL,
85
+ bdrv_dirty_bitmap_get_persistance);
86
}
87
88
/**
89
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
90
index XXXXXXX..XXXXXXX 100644
91
--- a/include/block/dirty-bitmap.h
92
+++ b/include/block/dirty-bitmap.h
93
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
94
void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap);
95
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
96
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
97
+void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs);
98
void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
99
const char *name,
100
Error **errp);
101
--
139
--
102
1.8.3.1
140
2.37.3
103
104
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Add bitmap extension as specified in docs/specs/qcow2.txt.
3
This is incorrect because qcow2_mark_clean() calls qcow2_flush_caches().
4
For now, just mirror extension header into Qcow2 state and check
4
qcow2_mark_clean() is called from non-coroutine context in
5
constraints. Also, calculate refcounts for qcow2 bitmaps, to not break
5
qcow2_inactivate() and qcow2_amend_options().
6
qemu-img check.
7
6
8
For now, disable image resize if it has bitmaps. It will be fixed later.
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-4-pbonzini@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/qcow2.h | 4 ++--
15
block/qcow2-refcount.c | 4 ++--
16
2 files changed, 4 insertions(+), 4 deletions(-)
9
17
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
diff --git a/block/qcow2.h b/block/qcow2.h
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Message-id: 20170628120530.31251-9-vsementsov@virtuozzo.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/Makefile.objs | 2 +-
17
block/qcow2-bitmap.c | 439 +++++++++++++++++++++++++++++++++++++++++++++++++
18
block/qcow2-refcount.c | 6 +
19
block/qcow2.c | 125 +++++++++++++-
20
block/qcow2.h | 27 +++
21
5 files changed, 593 insertions(+), 6 deletions(-)
22
create mode 100644 block/qcow2-bitmap.c
23
24
diff --git a/block/Makefile.objs b/block/Makefile.objs
25
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
26
--- a/block/Makefile.objs
20
--- a/block/qcow2.h
27
+++ b/block/Makefile.objs
21
+++ b/block/qcow2.h
28
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
29
block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
23
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
30
-block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
24
int64_t l1_table_offset, int l1_size, int addend);
31
+block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o
25
32
block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
26
-int coroutine_fn qcow2_flush_caches(BlockDriverState *bs);
33
block-obj-y += qed-check.o
27
-int coroutine_fn qcow2_write_caches(BlockDriverState *bs);
34
block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
28
+int qcow2_flush_caches(BlockDriverState *bs);
35
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
29
+int qcow2_write_caches(BlockDriverState *bs);
36
new file mode 100644
30
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
37
index XXXXXXX..XXXXXXX
31
BdrvCheckMode fix);
38
--- /dev/null
32
39
+++ b/block/qcow2-bitmap.c
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * Bitmaps for the QCOW version 2 format
43
+ *
44
+ * Copyright (c) 2014-2017 Vladimir Sementsov-Ogievskiy
45
+ *
46
+ * This file is derived from qcow2-snapshot.c, original copyright:
47
+ * Copyright (c) 2004-2006 Fabrice Bellard
48
+ *
49
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
50
+ * of this software and associated documentation files (the "Software"), to deal
51
+ * in the Software without restriction, including without limitation the rights
52
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
+ * copies of the Software, and to permit persons to whom the Software is
54
+ * furnished to do so, subject to the following conditions:
55
+ *
56
+ * The above copyright notice and this permission notice shall be included in
57
+ * all copies or substantial portions of the Software.
58
+ *
59
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
62
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65
+ * THE SOFTWARE.
66
+ */
67
+
68
+#include "qemu/osdep.h"
69
+#include "qapi/error.h"
70
+
71
+#include "block/block_int.h"
72
+#include "block/qcow2.h"
73
+
74
+/* NOTICE: BME here means Bitmaps Extension and used as a namespace for
75
+ * _internal_ constants. Please do not use this _internal_ abbreviation for
76
+ * other needs and/or outside of this file. */
77
+
78
+/* Bitmap directory entry constraints */
79
+#define BME_MAX_TABLE_SIZE 0x8000000
80
+#define BME_MAX_PHYS_SIZE 0x20000000 /* restrict BdrvDirtyBitmap size in RAM */
81
+#define BME_MAX_GRANULARITY_BITS 31
82
+#define BME_MIN_GRANULARITY_BITS 9
83
+#define BME_MAX_NAME_SIZE 1023
84
+
85
+/* Bitmap directory entry flags */
86
+#define BME_RESERVED_FLAGS 0xfffffffcU
87
+
88
+/* bits [1, 8] U [56, 63] are reserved */
89
+#define BME_TABLE_ENTRY_RESERVED_MASK 0xff000000000001feULL
90
+#define BME_TABLE_ENTRY_OFFSET_MASK 0x00fffffffffffe00ULL
91
+#define BME_TABLE_ENTRY_FLAG_ALL_ONES (1ULL << 0)
92
+
93
+typedef struct QEMU_PACKED Qcow2BitmapDirEntry {
94
+ /* header is 8 byte aligned */
95
+ uint64_t bitmap_table_offset;
96
+
97
+ uint32_t bitmap_table_size;
98
+ uint32_t flags;
99
+
100
+ uint8_t type;
101
+ uint8_t granularity_bits;
102
+ uint16_t name_size;
103
+ uint32_t extra_data_size;
104
+ /* extra data follows */
105
+ /* name follows */
106
+} Qcow2BitmapDirEntry;
107
+
108
+typedef struct Qcow2BitmapTable {
109
+ uint64_t offset;
110
+ uint32_t size; /* number of 64bit entries */
111
+ QSIMPLEQ_ENTRY(Qcow2BitmapTable) entry;
112
+} Qcow2BitmapTable;
113
+
114
+typedef struct Qcow2Bitmap {
115
+ Qcow2BitmapTable table;
116
+ uint32_t flags;
117
+ uint8_t granularity_bits;
118
+ char *name;
119
+
120
+ QSIMPLEQ_ENTRY(Qcow2Bitmap) entry;
121
+} Qcow2Bitmap;
122
+typedef QSIMPLEQ_HEAD(Qcow2BitmapList, Qcow2Bitmap) Qcow2BitmapList;
123
+
124
+typedef enum BitmapType {
125
+ BT_DIRTY_TRACKING_BITMAP = 1
126
+} BitmapType;
127
+
128
+static int check_table_entry(uint64_t entry, int cluster_size)
129
+{
130
+ uint64_t offset;
131
+
132
+ if (entry & BME_TABLE_ENTRY_RESERVED_MASK) {
133
+ return -EINVAL;
134
+ }
135
+
136
+ offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
137
+ if (offset != 0) {
138
+ /* if offset specified, bit 0 is reserved */
139
+ if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) {
140
+ return -EINVAL;
141
+ }
142
+
143
+ if (offset % cluster_size != 0) {
144
+ return -EINVAL;
145
+ }
146
+ }
147
+
148
+ return 0;
149
+}
150
+
151
+static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
152
+ uint64_t **bitmap_table)
153
+{
154
+ int ret;
155
+ BDRVQcow2State *s = bs->opaque;
156
+ uint32_t i;
157
+ uint64_t *table;
158
+
159
+ assert(tb->size != 0);
160
+ table = g_try_new(uint64_t, tb->size);
161
+ if (table == NULL) {
162
+ return -ENOMEM;
163
+ }
164
+
165
+ assert(tb->size <= BME_MAX_TABLE_SIZE);
166
+ ret = bdrv_pread(bs->file, tb->offset,
167
+ table, tb->size * sizeof(uint64_t));
168
+ if (ret < 0) {
169
+ goto fail;
170
+ }
171
+
172
+ for (i = 0; i < tb->size; ++i) {
173
+ be64_to_cpus(&table[i]);
174
+ ret = check_table_entry(table[i], s->cluster_size);
175
+ if (ret < 0) {
176
+ goto fail;
177
+ }
178
+ }
179
+
180
+ *bitmap_table = table;
181
+ return 0;
182
+
183
+fail:
184
+ g_free(table);
185
+
186
+ return ret;
187
+}
188
+
189
+/*
190
+ * Bitmap List
191
+ */
192
+
193
+/*
194
+ * Bitmap List private functions
195
+ * Only Bitmap List knows about bitmap directory structure in Qcow2.
196
+ */
197
+
198
+static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
199
+{
200
+ be64_to_cpus(&entry->bitmap_table_offset);
201
+ be32_to_cpus(&entry->bitmap_table_size);
202
+ be32_to_cpus(&entry->flags);
203
+ be16_to_cpus(&entry->name_size);
204
+ be32_to_cpus(&entry->extra_data_size);
205
+}
206
+
207
+static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
208
+{
209
+ return align_offset(sizeof(Qcow2BitmapDirEntry) +
210
+ name_size + extra_data_size, 8);
211
+}
212
+
213
+static inline int dir_entry_size(Qcow2BitmapDirEntry *entry)
214
+{
215
+ return calc_dir_entry_size(entry->name_size, entry->extra_data_size);
216
+}
217
+
218
+static inline const char *dir_entry_name_field(Qcow2BitmapDirEntry *entry)
219
+{
220
+ return (const char *)(entry + 1) + entry->extra_data_size;
221
+}
222
+
223
+static inline char *dir_entry_copy_name(Qcow2BitmapDirEntry *entry)
224
+{
225
+ const char *name_field = dir_entry_name_field(entry);
226
+ return g_strndup(name_field, entry->name_size);
227
+}
228
+
229
+static inline Qcow2BitmapDirEntry *next_dir_entry(Qcow2BitmapDirEntry *entry)
230
+{
231
+ return (Qcow2BitmapDirEntry *)((uint8_t *)entry + dir_entry_size(entry));
232
+}
233
+
234
+static int check_dir_entry(BlockDriverState *bs, Qcow2BitmapDirEntry *entry)
235
+{
236
+ BDRVQcow2State *s = bs->opaque;
237
+ uint64_t phys_bitmap_bytes;
238
+ int64_t len;
239
+
240
+ bool fail = (entry->bitmap_table_size == 0) ||
241
+ (entry->bitmap_table_offset == 0) ||
242
+ (entry->bitmap_table_offset % s->cluster_size) ||
243
+ (entry->bitmap_table_size > BME_MAX_TABLE_SIZE) ||
244
+ (entry->granularity_bits > BME_MAX_GRANULARITY_BITS) ||
245
+ (entry->granularity_bits < BME_MIN_GRANULARITY_BITS) ||
246
+ (entry->flags & BME_RESERVED_FLAGS) ||
247
+ (entry->name_size > BME_MAX_NAME_SIZE) ||
248
+ (entry->type != BT_DIRTY_TRACKING_BITMAP);
249
+
250
+ if (fail) {
251
+ return -EINVAL;
252
+ }
253
+
254
+ phys_bitmap_bytes = (uint64_t)entry->bitmap_table_size * s->cluster_size;
255
+ len = bdrv_getlength(bs);
256
+
257
+ if (len < 0) {
258
+ return len;
259
+ }
260
+
261
+ fail = (phys_bitmap_bytes > BME_MAX_PHYS_SIZE) ||
262
+ (len > ((phys_bitmap_bytes * 8) << entry->granularity_bits));
263
+
264
+ return fail ? -EINVAL : 0;
265
+}
266
+
267
+/*
268
+ * Bitmap List public functions
269
+ */
270
+
271
+static void bitmap_free(Qcow2Bitmap *bm)
272
+{
273
+ g_free(bm->name);
274
+ g_free(bm);
275
+}
276
+
277
+static void bitmap_list_free(Qcow2BitmapList *bm_list)
278
+{
279
+ Qcow2Bitmap *bm;
280
+
281
+ if (bm_list == NULL) {
282
+ return;
283
+ }
284
+
285
+ while ((bm = QSIMPLEQ_FIRST(bm_list)) != NULL) {
286
+ QSIMPLEQ_REMOVE_HEAD(bm_list, entry);
287
+ bitmap_free(bm);
288
+ }
289
+
290
+ g_free(bm_list);
291
+}
292
+
293
+static Qcow2BitmapList *bitmap_list_new(void)
294
+{
295
+ Qcow2BitmapList *bm_list = g_new(Qcow2BitmapList, 1);
296
+ QSIMPLEQ_INIT(bm_list);
297
+
298
+ return bm_list;
299
+}
300
+
301
+/* bitmap_list_load
302
+ * Get bitmap list from qcow2 image. Actually reads bitmap directory,
303
+ * checks it and convert to bitmap list.
304
+ */
305
+static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset,
306
+ uint64_t size, Error **errp)
307
+{
308
+ int ret;
309
+ BDRVQcow2State *s = bs->opaque;
310
+ uint8_t *dir, *dir_end;
311
+ Qcow2BitmapDirEntry *e;
312
+ uint32_t nb_dir_entries = 0;
313
+ Qcow2BitmapList *bm_list = NULL;
314
+
315
+ if (size == 0) {
316
+ error_setg(errp, "Requested bitmap directory size is zero");
317
+ return NULL;
318
+ }
319
+
320
+ if (size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
321
+ error_setg(errp, "Requested bitmap directory size is too big");
322
+ return NULL;
323
+ }
324
+
325
+ dir = g_try_malloc(size);
326
+ if (dir == NULL) {
327
+ error_setg(errp, "Failed to allocate space for bitmap directory");
328
+ return NULL;
329
+ }
330
+ dir_end = dir + size;
331
+
332
+ ret = bdrv_pread(bs->file, offset, dir, size);
333
+ if (ret < 0) {
334
+ error_setg_errno(errp, -ret, "Failed to read bitmap directory");
335
+ goto fail;
336
+ }
337
+
338
+ bm_list = bitmap_list_new();
339
+ for (e = (Qcow2BitmapDirEntry *)dir;
340
+ e < (Qcow2BitmapDirEntry *)dir_end;
341
+ e = next_dir_entry(e))
342
+ {
343
+ Qcow2Bitmap *bm;
344
+
345
+ if ((uint8_t *)(e + 1) > dir_end) {
346
+ goto broken_dir;
347
+ }
348
+
349
+ if (++nb_dir_entries > s->nb_bitmaps) {
350
+ error_setg(errp, "More bitmaps found than specified in header"
351
+ " extension");
352
+ goto fail;
353
+ }
354
+ bitmap_dir_entry_to_cpu(e);
355
+
356
+ if ((uint8_t *)next_dir_entry(e) > dir_end) {
357
+ goto broken_dir;
358
+ }
359
+
360
+ if (e->extra_data_size != 0) {
361
+ error_setg(errp, "Bitmap extra data is not supported");
362
+ goto fail;
363
+ }
364
+
365
+ ret = check_dir_entry(bs, e);
366
+ if (ret < 0) {
367
+ error_setg(errp, "Bitmap '%.*s' doesn't satisfy the constraints",
368
+ e->name_size, dir_entry_name_field(e));
369
+ goto fail;
370
+ }
371
+
372
+ bm = g_new(Qcow2Bitmap, 1);
373
+ bm->table.offset = e->bitmap_table_offset;
374
+ bm->table.size = e->bitmap_table_size;
375
+ bm->flags = e->flags;
376
+ bm->granularity_bits = e->granularity_bits;
377
+ bm->name = dir_entry_copy_name(e);
378
+ QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry);
379
+ }
380
+
381
+ if (nb_dir_entries != s->nb_bitmaps) {
382
+ error_setg(errp, "Less bitmaps found than specified in header"
383
+ " extension");
384
+ goto fail;
385
+ }
386
+
387
+ if ((uint8_t *)e != dir_end) {
388
+ goto broken_dir;
389
+ }
390
+
391
+ g_free(dir);
392
+ return bm_list;
393
+
394
+broken_dir:
395
+ ret = -EINVAL;
396
+ error_setg(errp, "Broken bitmap directory");
397
+
398
+fail:
399
+ g_free(dir);
400
+ bitmap_list_free(bm_list);
401
+
402
+ return NULL;
403
+}
404
+
405
+int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
406
+ void **refcount_table,
407
+ int64_t *refcount_table_size)
408
+{
409
+ int ret;
410
+ BDRVQcow2State *s = bs->opaque;
411
+ Qcow2BitmapList *bm_list;
412
+ Qcow2Bitmap *bm;
413
+
414
+ if (s->nb_bitmaps == 0) {
415
+ return 0;
416
+ }
417
+
418
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size,
419
+ s->bitmap_directory_offset,
420
+ s->bitmap_directory_size);
421
+ if (ret < 0) {
422
+ return ret;
423
+ }
424
+
425
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
426
+ s->bitmap_directory_size, NULL);
427
+ if (bm_list == NULL) {
428
+ res->corruptions++;
429
+ return -EINVAL;
430
+ }
431
+
432
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
433
+ uint64_t *bitmap_table = NULL;
434
+ int i;
435
+
436
+ ret = qcow2_inc_refcounts_imrt(bs, res,
437
+ refcount_table, refcount_table_size,
438
+ bm->table.offset,
439
+ bm->table.size * sizeof(uint64_t));
440
+ if (ret < 0) {
441
+ goto out;
442
+ }
443
+
444
+ ret = bitmap_table_load(bs, &bm->table, &bitmap_table);
445
+ if (ret < 0) {
446
+ res->corruptions++;
447
+ goto out;
448
+ }
449
+
450
+ for (i = 0; i < bm->table.size; ++i) {
451
+ uint64_t entry = bitmap_table[i];
452
+ uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
453
+
454
+ if (check_table_entry(entry, s->cluster_size) < 0) {
455
+ res->corruptions++;
456
+ continue;
457
+ }
458
+
459
+ if (offset == 0) {
460
+ continue;
461
+ }
462
+
463
+ ret = qcow2_inc_refcounts_imrt(bs, res,
464
+ refcount_table, refcount_table_size,
465
+ offset, s->cluster_size);
466
+ if (ret < 0) {
467
+ g_free(bitmap_table);
468
+ goto out;
469
+ }
470
+ }
471
+
472
+ g_free(bitmap_table);
473
+ }
474
+
475
+out:
476
+ bitmap_list_free(bm_list);
477
+
478
+ return ret;
479
+}
480
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
33
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
481
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
482
--- a/block/qcow2-refcount.c
35
--- a/block/qcow2-refcount.c
483
+++ b/block/qcow2-refcount.c
36
+++ b/block/qcow2-refcount.c
484
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
37
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry,
485
}
486
}
38
}
487
488
+ /* bitmaps */
489
+ ret = qcow2_check_bitmaps_refcounts(bs, res, refcount_table, nb_clusters);
490
+ if (ret < 0) {
491
+ return ret;
492
+ }
493
+
494
return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters);
495
}
39
}
496
40
497
diff --git a/block/qcow2.c b/block/qcow2.c
41
-int coroutine_fn qcow2_write_caches(BlockDriverState *bs)
498
index XXXXXXX..XXXXXXX 100644
42
+int qcow2_write_caches(BlockDriverState *bs)
499
--- a/block/qcow2.c
500
+++ b/block/qcow2.c
501
@@ -XXX,XX +XXX,XX @@ typedef struct {
502
#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
503
#define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857
504
#define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77
505
+#define QCOW2_EXT_MAGIC_BITMAPS 0x23852875
506
507
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
508
{
509
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
510
*/
511
static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
512
uint64_t end_offset, void **p_feature_table,
513
- int flags, Error **errp)
514
+ int flags, bool *need_update_header,
515
+ Error **errp)
516
{
43
{
517
BDRVQcow2State *s = bs->opaque;
44
BDRVQcow2State *s = bs->opaque;
518
QCowExtension ext;
519
uint64_t offset;
520
int ret;
45
int ret;
521
+ Qcow2BitmapHeaderExt bitmaps_ext;
46
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_write_caches(BlockDriverState *bs)
522
+
47
return 0;
523
+ if (need_update_header != NULL) {
48
}
524
+ *need_update_header = false;
49
525
+ }
50
-int coroutine_fn qcow2_flush_caches(BlockDriverState *bs)
526
51
+int qcow2_flush_caches(BlockDriverState *bs)
527
#ifdef DEBUG_EXT
52
{
528
printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);
53
int ret = qcow2_write_caches(bs);
529
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
530
}
531
} break;
532
533
+ case QCOW2_EXT_MAGIC_BITMAPS:
534
+ if (ext.len != sizeof(bitmaps_ext)) {
535
+ error_setg_errno(errp, -ret, "bitmaps_ext: "
536
+ "Invalid extension length");
537
+ return -EINVAL;
538
+ }
539
+
540
+ if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) {
541
+ error_report("WARNING: a program lacking bitmap support "
542
+ "modified this file, so all bitmaps are now "
543
+ "considered inconsistent. Some clusters may be "
544
+ "leaked, run 'qemu-img check -r' on the image "
545
+ "file to fix.");
546
+ if (need_update_header != NULL) {
547
+ /* Updating is needed to drop invalid bitmap extension. */
548
+ *need_update_header = true;
549
+ }
550
+ break;
551
+ }
552
+
553
+ ret = bdrv_pread(bs->file, offset, &bitmaps_ext, ext.len);
554
+ if (ret < 0) {
555
+ error_setg_errno(errp, -ret, "bitmaps_ext: "
556
+ "Could not read ext header");
557
+ return ret;
558
+ }
559
+
560
+ if (bitmaps_ext.reserved32 != 0) {
561
+ error_setg_errno(errp, -ret, "bitmaps_ext: "
562
+ "Reserved field is not zero");
563
+ return -EINVAL;
564
+ }
565
+
566
+ be32_to_cpus(&bitmaps_ext.nb_bitmaps);
567
+ be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
568
+ be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
569
+
570
+ if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
571
+ error_setg(errp,
572
+ "bitmaps_ext: Image has %" PRIu32 " bitmaps, "
573
+ "exceeding the QEMU supported maximum of %d",
574
+ bitmaps_ext.nb_bitmaps, QCOW2_MAX_BITMAPS);
575
+ return -EINVAL;
576
+ }
577
+
578
+ if (bitmaps_ext.nb_bitmaps == 0) {
579
+ error_setg(errp, "found bitmaps extension with zero bitmaps");
580
+ return -EINVAL;
581
+ }
582
+
583
+ if (bitmaps_ext.bitmap_directory_offset & (s->cluster_size - 1)) {
584
+ error_setg(errp, "bitmaps_ext: "
585
+ "invalid bitmap directory offset");
586
+ return -EINVAL;
587
+ }
588
+
589
+ if (bitmaps_ext.bitmap_directory_size >
590
+ QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
591
+ error_setg(errp, "bitmaps_ext: "
592
+ "bitmap directory size (%" PRIu64 ") exceeds "
593
+ "the maximum supported size (%d)",
594
+ bitmaps_ext.bitmap_directory_size,
595
+ QCOW2_MAX_BITMAP_DIRECTORY_SIZE);
596
+ return -EINVAL;
597
+ }
598
+
599
+ s->nb_bitmaps = bitmaps_ext.nb_bitmaps;
600
+ s->bitmap_directory_offset =
601
+ bitmaps_ext.bitmap_directory_offset;
602
+ s->bitmap_directory_size =
603
+ bitmaps_ext.bitmap_directory_size;
604
+
605
+#ifdef DEBUG_EXT
606
+ printf("Qcow2: Got bitmaps extension: "
607
+ "offset=%" PRIu64 " nb_bitmaps=%" PRIu32 "\n",
608
+ s->bitmap_directory_offset, s->nb_bitmaps);
609
+#endif
610
+ break;
611
+
612
default:
613
/* unknown magic - save it in case we need to rewrite the header */
614
{
615
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
616
Error *local_err = NULL;
617
uint64_t ext_end;
618
uint64_t l1_vm_state_index;
619
+ bool update_header = false;
620
621
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
622
if (ret < 0) {
54
if (ret < 0) {
623
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
624
if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
625
void *feature_table = NULL;
626
qcow2_read_extensions(bs, header.header_length, ext_end,
627
- &feature_table, flags, NULL);
628
+ &feature_table, flags, NULL, NULL);
629
report_unsupported_feature(errp, feature_table,
630
s->incompatible_features &
631
~QCOW2_INCOMPAT_MASK);
632
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
633
634
/* read qcow2 extensions */
635
if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL,
636
- flags, &local_err)) {
637
+ flags, &update_header, &local_err)) {
638
error_propagate(errp, local_err);
639
ret = -EINVAL;
640
goto fail;
641
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
642
}
643
644
/* Clear unknown autoclear feature bits */
645
- if (!bs->read_only && !(flags & BDRV_O_INACTIVE) && s->autoclear_features) {
646
- s->autoclear_features = 0;
647
+ update_header |= s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK;
648
+
649
+ if (update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE)) {
650
+ s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
651
ret = qcow2_update_header(bs);
652
if (ret < 0) {
653
error_setg_errno(errp, -ret, "Could not update qcow2 header");
654
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
655
buflen -= ret;
656
}
657
658
+ /* Bitmap extension */
659
+ if (s->nb_bitmaps > 0) {
660
+ Qcow2BitmapHeaderExt bitmaps_header = {
661
+ .nb_bitmaps = cpu_to_be32(s->nb_bitmaps),
662
+ .bitmap_directory_size =
663
+ cpu_to_be64(s->bitmap_directory_size),
664
+ .bitmap_directory_offset =
665
+ cpu_to_be64(s->bitmap_directory_offset)
666
+ };
667
+ ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BITMAPS,
668
+ &bitmaps_header, sizeof(bitmaps_header),
669
+ buflen);
670
+ if (ret < 0) {
671
+ goto fail;
672
+ }
673
+ buf += ret;
674
+ buflen -= ret;
675
+ }
676
+
677
/* Keep unknown header extensions */
678
QLIST_FOREACH(uext, &s->unknown_header_ext, next) {
679
ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen);
680
@@ -XXX,XX +XXX,XX @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset, Error **errp)
681
return -ENOTSUP;
682
}
683
684
+ /* cannot proceed if image has bitmaps */
685
+ if (s->nb_bitmaps) {
686
+ /* TODO: resize bitmaps in the image */
687
+ error_setg(errp, "Can't resize an image which has bitmaps");
688
+ return -ENOTSUP;
689
+ }
690
+
691
/* shrinking is currently not supported */
692
if (offset < bs->total_sectors * 512) {
693
error_setg(errp, "qcow2 doesn't support shrinking images yet");
694
diff --git a/block/qcow2.h b/block/qcow2.h
695
index XXXXXXX..XXXXXXX 100644
696
--- a/block/qcow2.h
697
+++ b/block/qcow2.h
698
@@ -XXX,XX +XXX,XX @@
699
* space for snapshot names and IDs */
700
#define QCOW_MAX_SNAPSHOTS_SIZE (1024 * QCOW_MAX_SNAPSHOTS)
701
702
+/* Bitmap header extension constraints */
703
+#define QCOW2_MAX_BITMAPS 65535
704
+#define QCOW2_MAX_BITMAP_DIRECTORY_SIZE (1024 * QCOW2_MAX_BITMAPS)
705
+
706
/* indicate that the refcount of the referenced cluster is exactly one. */
707
#define QCOW_OFLAG_COPIED (1ULL << 63)
708
/* indicate that the cluster is compressed (they never have the copied flag) */
709
@@ -XXX,XX +XXX,XX @@ enum {
710
QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS,
711
};
712
713
+/* Autoclear feature bits */
714
+enum {
715
+ QCOW2_AUTOCLEAR_BITMAPS_BITNR = 0,
716
+ QCOW2_AUTOCLEAR_BITMAPS = 1 << QCOW2_AUTOCLEAR_BITMAPS_BITNR,
717
+
718
+ QCOW2_AUTOCLEAR_MASK = QCOW2_AUTOCLEAR_BITMAPS,
719
+};
720
+
721
enum qcow2_discard_type {
722
QCOW2_DISCARD_NEVER = 0,
723
QCOW2_DISCARD_ALWAYS,
724
@@ -XXX,XX +XXX,XX @@ typedef uint64_t Qcow2GetRefcountFunc(const void *refcount_array,
725
typedef void Qcow2SetRefcountFunc(void *refcount_array,
726
uint64_t index, uint64_t value);
727
728
+typedef struct Qcow2BitmapHeaderExt {
729
+ uint32_t nb_bitmaps;
730
+ uint32_t reserved32;
731
+ uint64_t bitmap_directory_size;
732
+ uint64_t bitmap_directory_offset;
733
+} QEMU_PACKED Qcow2BitmapHeaderExt;
734
+
735
typedef struct BDRVQcow2State {
736
int cluster_bits;
737
int cluster_size;
738
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
739
unsigned int nb_snapshots;
740
QCowSnapshot *snapshots;
741
742
+ uint32_t nb_bitmaps;
743
+ uint64_t bitmap_directory_size;
744
+ uint64_t bitmap_directory_offset;
745
+
746
int flags;
747
int qcow_version;
748
bool use_lazy_refcounts;
749
@@ -XXX,XX +XXX,XX @@ int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
750
void **table);
751
void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
752
753
+/* qcow2-bitmap.c functions */
754
+int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
755
+ void **refcount_table,
756
+ int64_t *refcount_table_size);
757
#endif
758
--
55
--
759
1.8.3.1
56
2.37.3
760
761
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Realize .bdrv_can_store_new_dirty_bitmap interface.
3
nbd_co_establish_connection_cancel() cancels a coroutine but is not called
4
from coroutine context itself, for example in nbd_cancel_in_flight()
5
and in timer callbacks reconnect_delay_timer_cb() and open_timer_cb().
4
6
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-id: 20170628120530.31251-23-vsementsov@virtuozzo.com
10
Message-Id: <20220922084924.201610-5-pbonzini@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
block/qcow2-bitmap.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
14
include/block/nbd.h | 2 +-
12
block/qcow2.c | 1 +
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
block/qcow2.h | 4 ++++
14
3 files changed, 56 insertions(+)
15
16
16
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
17
diff --git a/include/block/nbd.h b/include/block/nbd.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-bitmap.c
19
--- a/include/block/nbd.h
19
+++ b/block/qcow2-bitmap.c
20
+++ b/include/block/nbd.h
20
@@ -XXX,XX +XXX,XX @@ int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ QIOChannel *coroutine_fn
21
22
nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
22
return 0;
23
bool blocking, Error **errp);
23
}
24
24
+
25
-void coroutine_fn nbd_co_establish_connection_cancel(NBDClientConnection *conn);
25
+bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
26
+void nbd_co_establish_connection_cancel(NBDClientConnection *conn);
26
+ const char *name,
27
+ uint32_t granularity,
28
+ Error **errp)
29
+{
30
+ BDRVQcow2State *s = bs->opaque;
31
+ bool found;
32
+ Qcow2BitmapList *bm_list;
33
+
34
+ if (check_constraints_on_bitmap(bs, name, granularity, errp) != 0) {
35
+ goto fail;
36
+ }
37
+
38
+ if (s->nb_bitmaps == 0) {
39
+ return true;
40
+ }
41
+
42
+ if (s->nb_bitmaps >= QCOW2_MAX_BITMAPS) {
43
+ error_setg(errp,
44
+ "Maximum number of persistent bitmaps is already reached");
45
+ goto fail;
46
+ }
47
+
48
+ if (s->bitmap_directory_size + calc_dir_entry_size(strlen(name), 0) >
49
+ QCOW2_MAX_BITMAP_DIRECTORY_SIZE)
50
+ {
51
+ error_setg(errp, "Not enough space in the bitmap directory");
52
+ goto fail;
53
+ }
54
+
55
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
56
+ s->bitmap_directory_size, errp);
57
+ if (bm_list == NULL) {
58
+ goto fail;
59
+ }
60
+
61
+ found = find_bitmap_by_name(bm_list, name);
62
+ bitmap_list_free(bm_list);
63
+ if (found) {
64
+ error_setg(errp, "Bitmap with the same name is already stored");
65
+ goto fail;
66
+ }
67
+
68
+ return true;
69
+
70
+fail:
71
+ error_prepend(errp, "Can't make bitmap '%s' persistent in '%s': ",
72
+ name, bdrv_get_device_or_node_name(bs));
73
+ return false;
74
+}
75
diff --git a/block/qcow2.c b/block/qcow2.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/qcow2.c
78
+++ b/block/qcow2.c
79
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
80
.bdrv_attach_aio_context = qcow2_attach_aio_context,
81
82
.bdrv_reopen_bitmaps_rw = qcow2_reopen_bitmaps_rw,
83
+ .bdrv_can_store_new_dirty_bitmap = qcow2_can_store_new_dirty_bitmap,
84
};
85
86
static void bdrv_qcow2_init(void)
87
diff --git a/block/qcow2.h b/block/qcow2.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/qcow2.h
90
+++ b/block/qcow2.h
91
@@ -XXX,XX +XXX,XX @@ bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
92
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
93
void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
94
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
95
+bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
96
+ const char *name,
97
+ uint32_t granularity,
98
+ Error **errp);
99
27
100
#endif
28
#endif
101
--
29
--
102
1.8.3.1
30
2.37.3
103
104
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Make getter signature const-correct. This allows other functions with
3
qemu_coroutine_get_aio_context inspects a coroutine, but it does
4
const dirty bitmap parameter use bdrv_dirty_bitmap_granularity().
4
not have to be called from the coroutine itself (or from any
5
coroutine).
5
6
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-6-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Message-id: 20170628120530.31251-6-vsementsov@virtuozzo.com
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
---
13
block/dirty-bitmap.c | 2 +-
14
include/qemu/coroutine.h | 2 +-
14
include/block/dirty-bitmap.h | 2 +-
15
util/qemu-coroutine.c | 2 +-
15
2 files changed, 2 insertions(+), 2 deletions(-)
16
2 files changed, 2 insertions(+), 2 deletions(-)
16
17
17
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
18
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/block/dirty-bitmap.c
20
--- a/include/qemu/coroutine.h
20
+++ b/block/dirty-bitmap.c
21
+++ b/include/qemu/coroutine.h
21
@@ -XXX,XX +XXX,XX @@ uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs)
22
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_coroutine_yield(void);
22
return granularity;
23
/**
24
* Get the AioContext of the given coroutine
25
*/
26
-AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co);
27
+AioContext *qemu_coroutine_get_aio_context(Coroutine *co);
28
29
/**
30
* Get the currently executing coroutine
31
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/util/qemu-coroutine.c
34
+++ b/util/qemu-coroutine.c
35
@@ -XXX,XX +XXX,XX @@ bool qemu_coroutine_entered(Coroutine *co)
36
return co->caller;
23
}
37
}
24
38
25
-uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap)
39
-AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co)
26
+uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap)
40
+AioContext *qemu_coroutine_get_aio_context(Coroutine *co)
27
{
41
{
28
return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap);
42
return co->ctx;
29
}
43
}
30
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/block/dirty-bitmap.h
33
+++ b/include/block/dirty-bitmap.h
34
@@ -XXX,XX +XXX,XX @@ void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
35
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
36
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
37
uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs);
38
-uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap);
39
+uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap);
40
uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap);
41
bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap);
42
bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap);
43
--
44
--
44
1.8.3.1
45
2.37.3
45
46
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
POSIX says that backslashes in the arguments to 'echo', as well as
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
any use of 'echo -n' and 'echo -e', are non-portable; it recommends
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
people should favor 'printf' instead. This is definitely true where
5
functions where this holds.
6
we do not control which shell is running (such as in makefile snippets
7
or in documentation examples). But even for scripts where we
8
require bash (and therefore, where echo does what we want by default),
9
it is still possible to use 'shopt -s xpg_echo' to change bash's
10
behavior of echo. And setting a good example never hurts when we are
11
not sure if a snippet will be copied from a bash-only script to a
12
general shell script (although I don't change the use of non-portable
13
\e for ESC when we know the running shell is bash).
14
6
15
Replace 'echo -n "..."' with 'printf %s "..."', and 'echo -e "..."'
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
16
with 'printf %b "...\n"', with the optimization that the %s/%b
8
Reviewed-by: Eric Blake <eblake@redhat.com>
17
argument can be omitted if the string being printed is a strict
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
18
literal with no '%', '$', or '`' (we could technically also make
10
Message-Id: <20220922084924.201610-8-pbonzini@redhat.com>
19
this optimization when there are $ or `` substitutions but where
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
20
we can prove their results will not be problematic, but proving
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
that such substitutions are safe makes the patch less trivial
13
---
22
compared to just being consistent).
14
block/blkverify.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
23
16
24
In the qemu-iotests check script, fix unusual shell quoting
17
diff --git a/block/blkverify.c b/block/blkverify.c
25
that would result in word-splitting if 'date' outputs a space.
26
27
In test 051, take an opportunity to shorten the line.
28
29
In test 068, get rid of a pointless second invocation of bash.
30
31
CC: qemu-trivial@nongnu.org
32
Signed-off-by: Eric Blake <eblake@redhat.com>
33
Message-id: 20170703180950.9895-1-eblake@redhat.com
34
Signed-off-by: Max Reitz <mreitz@redhat.com>
35
---
36
qemu-options.hx | 4 ++--
37
tests/multiboot/run_test.sh | 10 +++++-----
38
tests/qemu-iotests/051 | 7 ++++---
39
tests/qemu-iotests/068 | 2 +-
40
tests/qemu-iotests/142 | 48 ++++++++++++++++++++++-----------------------
41
tests/qemu-iotests/171 | 14 ++++++-------
42
tests/qemu-iotests/check | 18 ++++++++---------
43
tests/rocker/all | 10 +++++-----
44
tests/tcg/cris/Makefile | 8 ++++----
45
9 files changed, 61 insertions(+), 60 deletions(-)
46
47
diff --git a/qemu-options.hx b/qemu-options.hx
48
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-options.hx
19
--- a/block/blkverify.c
50
+++ b/qemu-options.hx
20
+++ b/block/blkverify.c
51
@@ -XXX,XX +XXX,XX @@ The simplest (insecure) usage is to provide the secret inline
21
@@ -XXX,XX +XXX,XX @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
52
22
return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
53
The simplest secure usage is to provide the secret via a file
54
55
- # echo -n "letmein" > mypasswd.txt
56
+ # printf "letmein" > mypasswd.txt
57
# $QEMU -object secret,id=sec0,file=mypasswd.txt,format=raw
58
59
For greater security, AES-256-CBC should be used. To illustrate usage,
60
@@ -XXX,XX +XXX,XX @@ telling openssl to base64 encode the result, but it could be left
61
as raw bytes if desired.
62
63
@example
64
- # SECRET=$(echo -n "letmein" |
65
+ # SECRET=$(printf "letmein" |
66
openssl enc -aes-256-cbc -a -K $KEY -iv $IV)
67
@end example
68
69
diff --git a/tests/multiboot/run_test.sh b/tests/multiboot/run_test.sh
70
index XXXXXXX..XXXXXXX 100755
71
--- a/tests/multiboot/run_test.sh
72
+++ b/tests/multiboot/run_test.sh
73
@@ -XXX,XX +XXX,XX @@ run_qemu() {
74
local kernel=$1
75
shift
76
77
- echo -e "\n\n=== Running test case: $kernel $@ ===\n" >> test.log
78
+ printf %b "\n\n=== Running test case: $kernel $@ ===\n\n" >> test.log
79
80
$QEMU \
81
-kernel $kernel \
82
@@ -XXX,XX +XXX,XX @@ for t in mmap modules; do
83
pass=1
84
85
if [ $debugexit != 1 ]; then
86
- echo -e "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)"
87
+ printf %b "\e[31m ?? \e[0m $t (no debugexit used, exit code $ret)\n"
88
pass=0
89
elif [ $ret != 0 ]; then
90
- echo -e "\e[31mFAIL\e[0m $t (exit code $ret)"
91
+ printf %b "\e[31mFAIL\e[0m $t (exit code $ret)\n"
92
pass=0
93
fi
94
95
if ! diff $t.out test.log > /dev/null 2>&1; then
96
- echo -e "\e[31mFAIL\e[0m $t (output difference)"
97
+ printf %b "\e[31mFAIL\e[0m $t (output difference)\n"
98
diff -u $t.out test.log
99
pass=0
100
fi
101
102
if [ $pass == 1 ]; then
103
- echo -e "\e[32mPASS\e[0m $t"
104
+ printf %b "\e[32mPASS\e[0m $t\n"
105
fi
106
107
done
108
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
109
index XXXXXXX..XXXXXXX 100755
110
--- a/tests/qemu-iotests/051
111
+++ b/tests/qemu-iotests/051
112
@@ -XXX,XX +XXX,XX @@ run_qemu -drive driver=null-co,cache=invalid_value
113
# Test 142 checks the direct=on cases
114
115
for cache in writeback writethrough unsafe invalid_value; do
116
- echo -e "info block\ninfo block file\ninfo block backing\ninfo block backing-file" | \
117
+ printf "info block %s\n" '' file backing backing-file | \
118
run_qemu -drive file="$TEST_IMG",cache=$cache,backing.file.filename="$TEST_IMG.base",backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=$device_id -nodefaults
119
done
120
121
@@ -XXX,XX +XXX,XX @@ echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_I
122
123
$QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io
124
125
-echo -e "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id\
126
- | _filter_qemu_io
127
+printf %b "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id\n" |
128
+ run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id |
129
+ _filter_qemu_io
130
131
$QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
132
133
diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068
134
index XXXXXXX..XXXXXXX 100755
135
--- a/tests/qemu-iotests/068
136
+++ b/tests/qemu-iotests/068
137
@@ -XXX,XX +XXX,XX @@ for extra_args in \
138
_make_test_img $IMG_SIZE
139
140
# Give qemu some time to boot before saving the VM state
141
- bash -c 'sleep 1; echo -e "savevm 0\nquit"' | _qemu $extra_args
142
+ { sleep 1; printf "savevm 0\nquit\n"; } | _qemu $extra_args
143
# Now try to continue from that VM state (this should just work)
144
echo quit | _qemu $extra_args -loadvm 0
145
done
146
diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142
147
index XXXXXXX..XXXXXXX 100755
148
--- a/tests/qemu-iotests/142
149
+++ b/tests/qemu-iotests/142
150
@@ -XXX,XX +XXX,XX @@ function check_cache_all()
151
# cache.direct is supposed to be inherited by both bs->file and
152
# bs->backing
153
154
- echo -e "cache.direct=on on none0"
155
+ printf "cache.direct=on on none0\n"
156
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
157
- echo -e "\ncache.direct=on on file"
158
+ printf "\ncache.direct=on on file\n"
159
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
160
- echo -e "\ncache.direct=on on backing"
161
+ printf "\ncache.direct=on on backing\n"
162
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
163
- echo -e "\ncache.direct=on on backing-file"
164
+ printf "\ncache.direct=on on backing-file\n"
165
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
166
167
# cache.writeback is supposed to be inherited by bs->backing; bs->file
168
# always gets cache.writeback=on
169
170
- echo -e "\n\ncache.writeback=off on none0"
171
+ printf "\n\ncache.writeback=off on none0\n"
172
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
173
- echo -e "\ncache.writeback=off on file"
174
+ printf "\ncache.writeback=off on file\n"
175
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep -e "doesn't" -e "does not"
176
- echo -e "\ncache.writeback=off on backing"
177
+ printf "\ncache.writeback=off on backing\n"
178
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep -e "doesn't" -e "does not"
179
- echo -e "\ncache.writeback=off on backing-file"
180
+ printf "\ncache.writeback=off on backing-file\n"
181
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep -e "doesn't" -e "does not"
182
183
# cache.no-flush is supposed to be inherited by both bs->file and bs->backing
184
185
- echo -e "\n\ncache.no-flush=on on none0"
186
+ printf "\n\ncache.no-flush=on on none0\n"
187
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
188
- echo -e "\ncache.no-flush=on on file"
189
+ printf "\ncache.no-flush=on on file\n"
190
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
191
- echo -e "\ncache.no-flush=on on backing"
192
+ printf "\ncache.no-flush=on on backing\n"
193
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
194
- echo -e "\ncache.no-flush=on on backing-file"
195
+ printf "\ncache.no-flush=on on backing-file\n"
196
echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
197
}
23
}
198
24
199
@@ -XXX,XX +XXX,XX @@ function check_cache_all_separate()
25
-static int blkverify_co_flush(BlockDriverState *bs)
26
+static int coroutine_fn blkverify_co_flush(BlockDriverState *bs)
200
{
27
{
201
# Check cache.direct
28
BDRVBlkverifyState *s = bs->opaque;
202
203
- echo -e "cache.direct=on on blk"
204
+ printf "cache.direct=on on blk\n"
205
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
206
- echo -e "\ncache.direct=on on file"
207
+ printf "\ncache.direct=on on file\n"
208
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
209
- echo -e "\ncache.direct=on on backing"
210
+ printf "\ncache.direct=on on backing\n"
211
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
212
- echo -e "\ncache.direct=on on backing-file"
213
+ printf "\ncache.direct=on on backing-file\n"
214
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
215
216
# Check cache.writeback
217
218
- echo -e "\n\ncache.writeback=off on blk"
219
+ printf "\n\ncache.writeback=off on blk\n"
220
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
221
- echo -e "\ncache.writeback=off on file"
222
+ printf "\ncache.writeback=off on file\n"
223
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
224
- echo -e "\ncache.writeback=off on backing"
225
+ printf "\ncache.writeback=off on backing\n"
226
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
227
- echo -e "\ncache.writeback=off on backing-file"
228
+ printf "\ncache.writeback=off on backing-file\n"
229
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
230
231
# Check cache.no-flush
232
233
- echo -e "\n\ncache.no-flush=on on blk"
234
+ printf "\n\ncache.no-flush=on on blk\n"
235
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
236
- echo -e "\ncache.no-flush=on on file"
237
+ printf "\ncache.no-flush=on on file\n"
238
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
239
- echo -e "\ncache.no-flush=on on backing"
240
+ printf "\ncache.no-flush=on on backing\n"
241
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
242
- echo -e "\ncache.no-flush=on on backing-file"
243
+ printf "\ncache.no-flush=on on backing-file\n"
244
echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
245
}
246
247
diff --git a/tests/qemu-iotests/171 b/tests/qemu-iotests/171
248
index XXXXXXX..XXXXXXX 100755
249
--- a/tests/qemu-iotests/171
250
+++ b/tests/qemu-iotests/171
251
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
252
253
# Create JSON with options
254
img_json() {
255
- echo -n 'json:{"driver":"raw", '
256
- echo -n "\"offset\":\"$img_offset\", "
257
+ printf %s 'json:{"driver":"raw", '
258
+ printf %s "\"offset\":\"$img_offset\", "
259
if [ "$img_size" -ne -1 ] ; then
260
- echo -n "\"size\":\"$img_size\", "
261
+ printf %s "\"size\":\"$img_size\", "
262
fi
263
- echo -n '"file": {'
264
- echo -n '"driver":"file", '
265
- echo -n "\"filename\":\"$TEST_IMG\" "
266
- echo -n "} }"
267
+ printf %s '"file": {'
268
+ printf %s '"driver":"file", '
269
+ printf %s "\"filename\":\"$TEST_IMG\" "
270
+ printf %s "} }"
271
}
272
273
do_general_test() {
274
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
275
index XXXXXXX..XXXXXXX 100755
276
--- a/tests/qemu-iotests/check
277
+++ b/tests/qemu-iotests/check
278
@@ -XXX,XX +XXX,XX @@ _wallclock()
279
_timestamp()
280
{
281
now=`date "+%T"`
282
- echo -n " [$now]"
283
+ printf %s " [$now]"
284
}
285
286
_wrapup()
287
@@ -XXX,XX +XXX,XX @@ seq="check"
288
for seq in $list
289
do
290
err=false
291
- echo -n "$seq"
292
+ printf %s "$seq"
293
if [ -n "$TESTS_REMAINING_LOG" ] ; then
294
sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp
295
mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG
296
@@ -XXX,XX +XXX,XX @@ do
297
rm -f $seq.out.bad
298
lasttime=`sed -n -e "/^$seq /s/.* //p" <$TIMESTAMP_FILE`
299
if [ "X$lasttime" != X ]; then
300
- echo -n " ${lasttime}s ..."
301
+ printf %s " ${lasttime}s ..."
302
else
303
- echo -n " " # prettier output with timestamps.
304
+ printf " " # prettier output with timestamps.
305
fi
306
rm -f core $seq.notrun
307
308
@@ -XXX,XX +XXX,XX @@ do
309
echo "$seq" > "${TEST_DIR}"/check.sts
310
311
start=`_wallclock`
312
- $timestamp && echo -n " ["`date "+%T"`"]"
313
+ $timestamp && printf %s " [$(date "+%T")]"
314
315
if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then
316
run_command="$PYTHON $seq"
317
@@ -XXX,XX +XXX,XX @@ do
318
319
if [ -f core ]
320
then
321
- echo -n " [dumped core]"
322
+ printf " [dumped core]"
323
mv core $seq.core
324
err=true
325
fi
326
327
if [ -f $seq.notrun ]
328
then
329
- $timestamp || echo -n " [not run] "
330
- $timestamp && echo " [not run]" && echo -n " $seq -- "
331
+ $timestamp || printf " [not run] "
332
+ $timestamp && echo " [not run]" && printf %s " $seq -- "
333
cat $seq.notrun
334
notrun="$notrun $seq"
335
else
336
if [ $sts -ne 0 ]
337
then
338
- echo -n " [failed, exit status $sts]"
339
+ printf %s " [failed, exit status $sts]"
340
err=true
341
fi
342
343
diff --git a/tests/rocker/all b/tests/rocker/all
344
index XXXXXXX..XXXXXXX 100755
345
--- a/tests/rocker/all
346
+++ b/tests/rocker/all
347
@@ -XXX,XX +XXX,XX @@
348
-echo -n "Running port test... "
349
+printf "Running port test... "
350
./port
351
if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi
352
353
-echo -n "Running bridge test... "
354
+printf "Running bridge test... "
355
./bridge
356
if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi
357
358
-echo -n "Running bridge STP test... "
359
+printf "Running bridge STP test... "
360
./bridge-stp
361
if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi
362
363
-echo -n "Running bridge VLAN test... "
364
+printf "Running bridge VLAN test... "
365
./bridge-vlan
366
if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi
367
368
-echo -n "Running bridge VLAN STP test... "
369
+printf "Running bridge VLAN STP test... "
370
./bridge-vlan-stp
371
if [ $? -eq 0 ]; then echo "pass"; else echo "FAILED"; exit 1; fi
372
diff --git a/tests/tcg/cris/Makefile b/tests/tcg/cris/Makefile
373
index XXXXXXX..XXXXXXX 100644
374
--- a/tests/tcg/cris/Makefile
375
+++ b/tests/tcg/cris/Makefile
376
@@ -XXX,XX +XXX,XX @@ check_addcv17.tst: crtv10.o sysv10.o
377
build: $(CRT) $(SYS) $(TESTCASES)
378
379
check: $(CRT) $(SYS) $(TESTCASES)
380
-    @echo -e "\nQEMU simulator."
381
+    @printf "\nQEMU simulator.\n"
382
    for case in $(TESTCASES); do \
383
-        echo -n "$$case "; \
384
+        printf %s "$$case "; \
385
        SIMARGS=; \
386
        case $$case in *v17*) SIMARGS="-cpu crisv17";; esac; \
387
        $(SIM) $$SIMARGS ./$$case; \
388
    done
389
check-g: $(CRT) $(SYS) $(TESTCASES)
390
-    @echo -e "\nGDB simulator."
391
+    @printf "\nGDB simulator.\n"
392
    @for case in $(TESTCASES); do \
393
-        echo -n "$$case "; \
394
+        printf %s "$$case "; \
395
        $(SIMG) $$case; \
396
    done
397
29
398
--
30
--
399
1.8.3.1
31
2.37.3
400
401
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Change the internal
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
loop iteration of committing to track by bytes instead of sectors
5
functions where this holds.
6
(although we are still guaranteed that we iterate by steps that
7
are sector-aligned).
8
6
9
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-9-pbonzini@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
block/commit.c | 16 ++++++----------
14
block/file-posix.c | 2 +-
16
1 file changed, 6 insertions(+), 10 deletions(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
17
16
18
diff --git a/block/commit.c b/block/commit.c
17
diff --git a/block/file-posix.c b/block/file-posix.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/block/commit.c
19
--- a/block/file-posix.c
21
+++ b/block/commit.c
20
+++ b/block/file-posix.c
22
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
21
@@ -XXX,XX +XXX,XX @@ static void raw_aio_unplug(BlockDriverState *bs)
22
#endif
23
}
24
25
-static int raw_co_flush_to_disk(BlockDriverState *bs)
26
+static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
23
{
27
{
24
CommitBlockJob *s = opaque;
28
BDRVRawState *s = bs->opaque;
25
CommitCompleteData *data;
29
RawPosixAIOData acb;
26
- int64_t sector_num, end;
27
+ int64_t offset;
28
uint64_t delay_ns = 0;
29
int ret = 0;
30
- int n = 0;
31
+ int n = 0; /* sectors */
32
void *buf = NULL;
33
int bytes_written = 0;
34
int64_t base_len;
35
36
ret = s->common.len = blk_getlength(s->top);
37
38
-
39
if (s->common.len < 0) {
40
goto out;
41
}
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
43
}
44
}
45
46
- end = s->common.len >> BDRV_SECTOR_BITS;
47
buf = blk_blockalign(s->top, COMMIT_BUFFER_SIZE);
48
49
- for (sector_num = 0; sector_num < end; sector_num += n) {
50
+ for (offset = 0; offset < s->common.len; offset += n * BDRV_SECTOR_SIZE) {
51
bool copy;
52
53
/* Note that even when no rate limit is applied we need to yield
54
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
55
}
56
/* Copy if allocated above the base */
57
ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base),
58
- sector_num,
59
+ offset / BDRV_SECTOR_SIZE,
60
COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
61
&n);
62
copy = (ret == 1);
63
- trace_commit_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
64
- n * BDRV_SECTOR_SIZE, ret);
65
+ trace_commit_one_iteration(s, offset, n * BDRV_SECTOR_SIZE, ret);
66
if (copy) {
67
- ret = commit_populate(s->top, s->base,
68
- sector_num * BDRV_SECTOR_SIZE,
69
+ ret = commit_populate(s->top, s->base, offset,
70
n * BDRV_SECTOR_SIZE, buf);
71
bytes_written += n * BDRV_SECTOR_SIZE;
72
}
73
--
30
--
74
1.8.3.1
31
2.37.3
75
76
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Continue by converting an
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
internal structure (no semantic change), and all references to the
5
functions where this holds.
6
buffer size.
7
6
8
Add an assertion that our use of s->granularity >> BDRV_SECTOR_BITS
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
(necessary for interaction with sector-based dirty bitmaps, until
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
a later patch converts those to be byte-based) does not suffer from
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
truncation problems.
10
Message-Id: <20220922084924.201610-10-pbonzini@redhat.com>
12
11
[kwolf: Fixed up coding style]
13
[checkpatch has a false positive on use of MIN() in this patch]
14
15
Signed-off-by: Eric Blake <eblake@redhat.com>
16
Reviewed-by: John Snow <jsnow@redhat.com>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
14
---
20
block/mirror.c | 84 +++++++++++++++++++++++++++++-----------------------------
15
block/iscsi.c | 3 ++-
21
1 file changed, 42 insertions(+), 42 deletions(-)
16
1 file changed, 2 insertions(+), 1 deletion(-)
22
17
23
diff --git a/block/mirror.c b/block/mirror.c
18
diff --git a/block/iscsi.c b/block/iscsi.c
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/block/mirror.c
20
--- a/block/iscsi.c
26
+++ b/block/mirror.c
21
+++ b/block/iscsi.c
27
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
28
29
#define SLICE_TIME 100000000ULL /* ns */
30
#define MAX_IN_FLIGHT 16
31
-#define MAX_IO_SECTORS ((1 << 20) >> BDRV_SECTOR_BITS) /* 1 Mb */
32
-#define DEFAULT_MIRROR_BUF_SIZE \
33
- (MAX_IN_FLIGHT * MAX_IO_SECTORS * BDRV_SECTOR_SIZE)
34
+#define MAX_IO_BYTES (1 << 20) /* 1 Mb */
35
+#define DEFAULT_MIRROR_BUF_SIZE (MAX_IN_FLIGHT * MAX_IO_BYTES)
36
37
/* The mirroring buffer is a list of granularity-sized chunks.
38
* Free chunks are organized in a list.
39
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob {
40
uint64_t last_pause_ns;
41
unsigned long *in_flight_bitmap;
42
int in_flight;
43
- int64_t sectors_in_flight;
44
+ int64_t bytes_in_flight;
45
int ret;
46
bool unmap;
47
bool waiting_for_io;
48
- int target_cluster_sectors;
49
+ int target_cluster_size;
50
int max_iov;
51
bool initial_zeroing_ongoing;
52
} MirrorBlockJob;
53
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBlockJob {
54
typedef struct MirrorOp {
55
MirrorBlockJob *s;
56
QEMUIOVector qiov;
57
- int64_t sector_num;
58
- int nb_sectors;
59
+ int64_t offset;
60
+ uint64_t bytes;
61
} MirrorOp;
62
63
static BlockErrorAction mirror_error_action(MirrorBlockJob *s, bool read,
64
@@ -XXX,XX +XXX,XX @@ static void mirror_iteration_done(MirrorOp *op, int ret)
65
MirrorBlockJob *s = op->s;
66
struct iovec *iov;
67
int64_t chunk_num;
68
- int i, nb_chunks, sectors_per_chunk;
69
+ int i, nb_chunks;
70
71
- trace_mirror_iteration_done(s, op->sector_num * BDRV_SECTOR_SIZE,
72
- op->nb_sectors * BDRV_SECTOR_SIZE, ret);
73
+ trace_mirror_iteration_done(s, op->offset, op->bytes, ret);
74
75
s->in_flight--;
76
- s->sectors_in_flight -= op->nb_sectors;
77
+ s->bytes_in_flight -= op->bytes;
78
iov = op->qiov.iov;
79
for (i = 0; i < op->qiov.niov; i++) {
80
MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base;
81
@@ -XXX,XX +XXX,XX @@ static void mirror_iteration_done(MirrorOp *op, int ret)
82
s->buf_free_count++;
83
}
84
85
- sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
86
- chunk_num = op->sector_num / sectors_per_chunk;
87
- nb_chunks = DIV_ROUND_UP(op->nb_sectors, sectors_per_chunk);
88
+ chunk_num = op->offset / s->granularity;
89
+ nb_chunks = DIV_ROUND_UP(op->bytes, s->granularity);
90
bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks);
91
if (ret >= 0) {
92
if (s->cow_bitmap) {
93
bitmap_set(s->cow_bitmap, chunk_num, nb_chunks);
94
}
95
if (!s->initial_zeroing_ongoing) {
96
- s->common.offset += (uint64_t)op->nb_sectors * BDRV_SECTOR_SIZE;
97
+ s->common.offset += op->bytes;
98
}
99
}
100
qemu_iovec_destroy(&op->qiov);
101
@@ -XXX,XX +XXX,XX @@ static void mirror_write_complete(void *opaque, int ret)
102
if (ret < 0) {
103
BlockErrorAction action;
104
105
- bdrv_set_dirty_bitmap(s->dirty_bitmap, op->sector_num, op->nb_sectors);
106
+ bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset >> BDRV_SECTOR_BITS,
107
+ op->bytes >> BDRV_SECTOR_BITS);
108
action = mirror_error_action(s, false, -ret);
109
if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
110
s->ret = ret;
111
@@ -XXX,XX +XXX,XX @@ static void mirror_read_complete(void *opaque, int ret)
112
if (ret < 0) {
113
BlockErrorAction action;
114
115
- bdrv_set_dirty_bitmap(s->dirty_bitmap, op->sector_num, op->nb_sectors);
116
+ bdrv_set_dirty_bitmap(s->dirty_bitmap, op->offset >> BDRV_SECTOR_BITS,
117
+ op->bytes >> BDRV_SECTOR_BITS);
118
action = mirror_error_action(s, true, -ret);
119
if (action == BLOCK_ERROR_ACTION_REPORT && s->ret >= 0) {
120
s->ret = ret;
121
@@ -XXX,XX +XXX,XX @@ static void mirror_read_complete(void *opaque, int ret)
122
123
mirror_iteration_done(op, ret);
124
} else {
125
- blk_aio_pwritev(s->target, op->sector_num * BDRV_SECTOR_SIZE, &op->qiov,
126
+ blk_aio_pwritev(s->target, op->offset, &op->qiov,
127
0, mirror_write_complete, op);
128
}
129
aio_context_release(blk_get_aio_context(s->common.blk));
130
@@ -XXX,XX +XXX,XX @@ static int mirror_cow_align(MirrorBlockJob *s,
131
align_nb_sectors = max_sectors;
132
if (need_cow) {
133
align_nb_sectors = QEMU_ALIGN_DOWN(align_nb_sectors,
134
- s->target_cluster_sectors);
135
+ s->target_cluster_size >>
136
+ BDRV_SECTOR_BITS);
137
}
138
}
139
/* Clipping may result in align_nb_sectors unaligned to chunk boundary, but
140
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
141
/* Allocate a MirrorOp that is used as an AIO callback. */
142
op = g_new(MirrorOp, 1);
143
op->s = s;
144
- op->sector_num = sector_num;
145
- op->nb_sectors = nb_sectors;
146
+ op->offset = sector_num * BDRV_SECTOR_SIZE;
147
+ op->bytes = nb_sectors * BDRV_SECTOR_SIZE;
148
149
/* Now make a QEMUIOVector taking enough granularity-sized chunks
150
* from s->buf_free.
151
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
152
153
/* Copy the dirty cluster. */
154
s->in_flight++;
155
- s->sectors_in_flight += nb_sectors;
156
+ s->bytes_in_flight += nb_sectors * BDRV_SECTOR_SIZE;
157
trace_mirror_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
158
nb_sectors * BDRV_SECTOR_SIZE);
159
160
@@ -XXX,XX +XXX,XX @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
161
* so the freeing in mirror_iteration_done is nop. */
162
op = g_new0(MirrorOp, 1);
163
op->s = s;
164
- op->sector_num = sector_num;
165
- op->nb_sectors = nb_sectors;
166
+ op->offset = sector_num * BDRV_SECTOR_SIZE;
167
+ op->bytes = nb_sectors * BDRV_SECTOR_SIZE;
168
169
s->in_flight++;
170
- s->sectors_in_flight += nb_sectors;
171
+ s->bytes_in_flight += nb_sectors * BDRV_SECTOR_SIZE;
172
if (is_discard) {
173
blk_aio_pdiscard(s->target, sector_num << BDRV_SECTOR_BITS,
174
- op->nb_sectors << BDRV_SECTOR_BITS,
175
- mirror_write_complete, op);
176
+ op->bytes, mirror_write_complete, op);
177
} else {
178
blk_aio_pwrite_zeroes(s->target, sector_num * BDRV_SECTOR_SIZE,
179
- op->nb_sectors * BDRV_SECTOR_SIZE,
180
- s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
181
+ op->bytes, s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
182
mirror_write_complete, op);
183
}
23
}
184
}
24
}
185
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
25
186
int64_t end = s->bdev_length / BDRV_SECTOR_SIZE;
26
-static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
187
int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
27
+static void coroutine_fn
188
bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
28
+iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
189
- int max_io_sectors = MAX((s->buf_size >> BDRV_SECTOR_BITS) / MAX_IN_FLIGHT,
29
{
190
- MAX_IO_SECTORS);
30
*iTask = (struct IscsiTask) {
191
+ int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES);
31
.co = qemu_coroutine_self(),
192
193
bdrv_dirty_bitmap_lock(s->dirty_bitmap);
194
sector_num = bdrv_dirty_iter_next(s->dbi);
195
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
196
nb_chunks * sectors_per_chunk,
197
&io_sectors, &file);
198
if (ret < 0) {
199
- io_sectors = MIN(nb_chunks * sectors_per_chunk, max_io_sectors);
200
+ io_sectors = MIN(nb_chunks * sectors_per_chunk,
201
+ max_io_bytes >> BDRV_SECTOR_BITS);
202
} else if (ret & BDRV_BLOCK_DATA) {
203
- io_sectors = MIN(io_sectors, max_io_sectors);
204
+ io_sectors = MIN(io_sectors, max_io_bytes >> BDRV_SECTOR_BITS);
205
}
206
207
io_sectors -= io_sectors % sectors_per_chunk;
208
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
209
char backing_filename[2]; /* we only need 2 characters because we are only
210
checking for a NULL string */
211
int ret = 0;
212
- int target_cluster_size = BDRV_SECTOR_SIZE;
213
214
if (block_job_is_cancelled(&s->common)) {
215
goto immediate_exit;
216
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
217
bdrv_get_backing_filename(target_bs, backing_filename,
218
sizeof(backing_filename));
219
if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) {
220
- target_cluster_size = bdi.cluster_size;
221
+ s->target_cluster_size = bdi.cluster_size;
222
+ } else {
223
+ s->target_cluster_size = BDRV_SECTOR_SIZE;
224
}
225
- if (backing_filename[0] && !target_bs->backing
226
- && s->granularity < target_cluster_size) {
227
- s->buf_size = MAX(s->buf_size, target_cluster_size);
228
+ if (backing_filename[0] && !target_bs->backing &&
229
+ s->granularity < s->target_cluster_size) {
230
+ s->buf_size = MAX(s->buf_size, s->target_cluster_size);
231
s->cow_bitmap = bitmap_new(length);
232
}
233
- s->target_cluster_sectors = target_cluster_size >> BDRV_SECTOR_BITS;
234
s->max_iov = MIN(bs->bl.max_iov, target_bs->bl.max_iov);
235
236
s->buf = qemu_try_blockalign(bs, s->buf_size);
237
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
238
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
239
/* s->common.offset contains the number of bytes already processed so
240
* far, cnt is the number of dirty sectors remaining and
241
- * s->sectors_in_flight is the number of sectors currently being
242
+ * s->bytes_in_flight is the number of bytes currently being
243
* processed; together those are the current total operation length */
244
- s->common.len = s->common.offset +
245
- (cnt + s->sectors_in_flight) * BDRV_SECTOR_SIZE;
246
+ s->common.len = s->common.offset + s->bytes_in_flight +
247
+ cnt * BDRV_SECTOR_SIZE;
248
249
/* Note that even when no rate limit is applied we need to yield
250
* periodically with no pending I/O so that bdrv_drain_all() returns.
251
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
252
}
253
254
assert ((granularity & (granularity - 1)) == 0);
255
+ /* Granularity must be large enough for sector-based dirty bitmap */
256
+ assert(granularity >= BDRV_SECTOR_SIZE);
257
258
if (buf_size < 0) {
259
error_setg(errp, "Invalid parameter 'buf-size'");
260
--
32
--
261
1.8.3.1
33
2.37.3
262
263
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Start by converting an
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
internal function (no semantic change).
5
functions where this holds.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Message-Id: <20220922084924.201610-11-pbonzini@redhat.com>
11
[kwolf: Fixed up coding style]
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
block/stream.c | 11 ++++++-----
15
block/nbd.c | 11 ++++++-----
14
1 file changed, 6 insertions(+), 5 deletions(-)
16
1 file changed, 6 insertions(+), 5 deletions(-)
15
17
16
diff --git a/block/stream.c b/block/stream.c
18
diff --git a/block/nbd.c b/block/nbd.c
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/block/stream.c
20
--- a/block/nbd.c
19
+++ b/block/stream.c
21
+++ b/block/nbd.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct StreamBlockJob {
22
@@ -XXX,XX +XXX,XX @@ static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret)
21
} StreamBlockJob;
23
* nbd_reply_chunk_iter_receive
22
24
* The pointer stored in @payload requires g_free() to free it.
23
static int coroutine_fn stream_populate(BlockBackend *blk,
25
*/
24
- int64_t sector_num, int nb_sectors,
26
-static bool nbd_reply_chunk_iter_receive(BDRVNBDState *s,
25
+ int64_t offset, uint64_t bytes,
27
- NBDReplyChunkIter *iter,
26
void *buf)
28
- uint64_t handle,
29
- QEMUIOVector *qiov, NBDReply *reply,
30
- void **payload)
31
+static bool coroutine_fn nbd_reply_chunk_iter_receive(BDRVNBDState *s,
32
+ NBDReplyChunkIter *iter,
33
+ uint64_t handle,
34
+ QEMUIOVector *qiov,
35
+ NBDReply *reply,
36
+ void **payload)
27
{
37
{
28
struct iovec iov = {
38
int ret, request_ret;
29
.iov_base = buf,
39
NBDReply local_reply;
30
- .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
31
+ .iov_len = bytes,
32
};
33
QEMUIOVector qiov;
34
35
+ assert(bytes < SIZE_MAX);
36
qemu_iovec_init_external(&qiov, &iov, 1);
37
38
/* Copy-on-read the unallocated clusters */
39
- return blk_co_preadv(blk, sector_num * BDRV_SECTOR_SIZE, qiov.size, &qiov,
40
- BDRV_REQ_COPY_ON_READ);
41
+ return blk_co_preadv(blk, offset, qiov.size, &qiov, BDRV_REQ_COPY_ON_READ);
42
}
43
44
typedef struct {
45
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
46
trace_stream_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
47
n * BDRV_SECTOR_SIZE, ret);
48
if (copy) {
49
- ret = stream_populate(blk, sector_num, n, buf);
50
+ ret = stream_populate(blk, sector_num * BDRV_SECTOR_SIZE,
51
+ n * BDRV_SECTOR_SIZE, buf);
52
}
53
if (ret < 0) {
54
BlockErrorAction action =
55
--
40
--
56
1.8.3.1
41
2.37.3
57
58
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Convert another internal
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
function (no semantic change).
5
functions where this holds.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Message-Id: <20220922084924.201610-12-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
12
---
13
block/backup.c | 62 ++++++++++++++++++++++++----------------------------------
13
block/nfs.c | 2 +-
14
1 file changed, 26 insertions(+), 36 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
15
16
diff --git a/block/backup.c b/block/backup.c
16
diff --git a/block/nfs.c b/block/nfs.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/backup.c
18
--- a/block/nfs.c
19
+++ b/block/backup.c
19
+++ b/block/nfs.c
20
@@ -XXX,XX +XXX,XX @@ static void cow_request_end(CowRequest *req)
20
@@ -XXX,XX +XXX,XX @@ static void nfs_process_write(void *arg)
21
qemu_mutex_unlock(&client->mutex);
21
}
22
}
22
23
23
static int coroutine_fn backup_do_cow(BackupBlockJob *job,
24
-static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
24
- int64_t sector_num, int nb_sectors,
25
+static void coroutine_fn nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
25
+ int64_t offset, uint64_t bytes,
26
bool *error_is_read,
27
bool is_write_notifier)
28
{
26
{
29
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
27
*task = (NFSRPC) {
30
QEMUIOVector bounce_qiov;
28
.co = qemu_coroutine_self(),
31
void *bounce_buffer = NULL;
32
int ret = 0;
33
- int64_t sectors_per_cluster = cluster_size_sectors(job);
34
- int64_t start, end; /* clusters */
35
+ int64_t start, end; /* bytes */
36
int n; /* bytes */
37
38
qemu_co_rwlock_rdlock(&job->flush_rwlock);
39
40
- start = sector_num / sectors_per_cluster;
41
- end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
42
+ start = QEMU_ALIGN_DOWN(offset, job->cluster_size);
43
+ end = QEMU_ALIGN_UP(bytes + offset, job->cluster_size);
44
45
- trace_backup_do_cow_enter(job, start * job->cluster_size,
46
- sector_num * BDRV_SECTOR_SIZE,
47
- nb_sectors * BDRV_SECTOR_SIZE);
48
+ trace_backup_do_cow_enter(job, start, offset, bytes);
49
50
- wait_for_overlapping_requests(job, start * job->cluster_size,
51
- end * job->cluster_size);
52
- cow_request_begin(&cow_request, job, start * job->cluster_size,
53
- end * job->cluster_size);
54
+ wait_for_overlapping_requests(job, start, end);
55
+ cow_request_begin(&cow_request, job, start, end);
56
57
- for (; start < end; start++) {
58
- if (test_bit(start, job->done_bitmap)) {
59
- trace_backup_do_cow_skip(job, start * job->cluster_size);
60
+ for (; start < end; start += job->cluster_size) {
61
+ if (test_bit(start / job->cluster_size, job->done_bitmap)) {
62
+ trace_backup_do_cow_skip(job, start);
63
continue; /* already copied */
64
}
65
66
- trace_backup_do_cow_process(job, start * job->cluster_size);
67
+ trace_backup_do_cow_process(job, start);
68
69
- n = MIN(job->cluster_size,
70
- job->common.len - start * job->cluster_size);
71
+ n = MIN(job->cluster_size, job->common.len - start);
72
73
if (!bounce_buffer) {
74
bounce_buffer = blk_blockalign(blk, job->cluster_size);
75
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
76
iov.iov_len = n;
77
qemu_iovec_init_external(&bounce_qiov, &iov, 1);
78
79
- ret = blk_co_preadv(blk, start * job->cluster_size,
80
- bounce_qiov.size, &bounce_qiov,
81
+ ret = blk_co_preadv(blk, start, bounce_qiov.size, &bounce_qiov,
82
is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
83
if (ret < 0) {
84
- trace_backup_do_cow_read_fail(job, start * job->cluster_size, ret);
85
+ trace_backup_do_cow_read_fail(job, start, ret);
86
if (error_is_read) {
87
*error_is_read = true;
88
}
89
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
90
}
91
92
if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
93
- ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
94
+ ret = blk_co_pwrite_zeroes(job->target, start,
95
bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
96
} else {
97
- ret = blk_co_pwritev(job->target, start * job->cluster_size,
98
+ ret = blk_co_pwritev(job->target, start,
99
bounce_qiov.size, &bounce_qiov,
100
job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
101
}
102
if (ret < 0) {
103
- trace_backup_do_cow_write_fail(job, start * job->cluster_size, ret);
104
+ trace_backup_do_cow_write_fail(job, start, ret);
105
if (error_is_read) {
106
*error_is_read = false;
107
}
108
goto out;
109
}
110
111
- set_bit(start, job->done_bitmap);
112
+ set_bit(start / job->cluster_size, job->done_bitmap);
113
114
/* Publish progress, guest I/O counts as progress too. Note that the
115
* offset field is an opaque progress value, it is not a disk offset.
116
@@ -XXX,XX +XXX,XX @@ out:
117
118
cow_request_end(&cow_request);
119
120
- trace_backup_do_cow_return(job, sector_num * BDRV_SECTOR_SIZE,
121
- nb_sectors * BDRV_SECTOR_SIZE, ret);
122
+ trace_backup_do_cow_return(job, offset, bytes, ret);
123
124
qemu_co_rwlock_unlock(&job->flush_rwlock);
125
126
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_before_write_notify(
127
{
128
BackupBlockJob *job = container_of(notifier, BackupBlockJob, before_write);
129
BdrvTrackedRequest *req = opaque;
130
- int64_t sector_num = req->offset >> BDRV_SECTOR_BITS;
131
- int nb_sectors = req->bytes >> BDRV_SECTOR_BITS;
132
133
assert(req->bs == blk_bs(job->common.blk));
134
- assert((req->offset & (BDRV_SECTOR_SIZE - 1)) == 0);
135
- assert((req->bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
136
+ assert(QEMU_IS_ALIGNED(req->offset, BDRV_SECTOR_SIZE));
137
+ assert(QEMU_IS_ALIGNED(req->bytes, BDRV_SECTOR_SIZE));
138
139
- return backup_do_cow(job, sector_num, nb_sectors, NULL, true);
140
+ return backup_do_cow(job, req->offset, req->bytes, NULL, true);
141
}
142
143
static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp)
144
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
145
if (yield_and_check(job)) {
146
goto out;
147
}
148
- ret = backup_do_cow(job, cluster * sectors_per_cluster,
149
- sectors_per_cluster, &error_is_read,
150
+ ret = backup_do_cow(job, cluster * job->cluster_size,
151
+ job->cluster_size, &error_is_read,
152
false);
153
if ((ret < 0) &&
154
backup_error_action(job, error_is_read, -ret) ==
155
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
156
if (alloced < 0) {
157
ret = alloced;
158
} else {
159
- ret = backup_do_cow(job, start * sectors_per_cluster,
160
- sectors_per_cluster, &error_is_read,
161
+ ret = backup_do_cow(job, start * job->cluster_size,
162
+ job->cluster_size, &error_is_read,
163
false);
164
}
165
if (ret < 0) {
166
--
29
--
167
1.8.3.1
30
2.37.3
168
169
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Now that the last user [mirror_iteration()] has converted to using
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
bytes, we no longer need a function to round sectors to clusters.
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
functions where this holds.
5
6
6
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Message-Id: <20220922084924.201610-13-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
13
---
12
block/io.c | 21 ---------------------
14
block/nvme.c | 6 ++++--
13
include/block/block.h | 4 ----
15
1 file changed, 4 insertions(+), 2 deletions(-)
14
2 files changed, 25 deletions(-)
15
16
16
diff --git a/block/io.c b/block/io.c
17
diff --git a/block/nvme.c b/block/nvme.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block/io.c
19
--- a/block/nvme.c
19
+++ b/block/io.c
20
+++ b/block/nvme.c
20
@@ -XXX,XX +XXX,XX @@ static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
21
@@ -XXX,XX +XXX,XX @@ static inline bool nvme_qiov_aligned(BlockDriverState *bs,
22
return true;
21
}
23
}
22
24
23
/**
25
-static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
24
- * Round a region to cluster boundaries (sector-based)
26
- QEMUIOVector *qiov, bool is_write, int flags)
25
- */
27
+static coroutine_fn int nvme_co_prw(BlockDriverState *bs,
26
-void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
28
+ uint64_t offset, uint64_t bytes,
27
- int64_t sector_num, int nb_sectors,
29
+ QEMUIOVector *qiov, bool is_write,
28
- int64_t *cluster_sector_num,
30
+ int flags)
29
- int *cluster_nb_sectors)
31
{
30
-{
32
BDRVNVMeState *s = bs->opaque;
31
- BlockDriverInfo bdi;
33
int r;
32
-
33
- if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
34
- *cluster_sector_num = sector_num;
35
- *cluster_nb_sectors = nb_sectors;
36
- } else {
37
- int64_t c = bdi.cluster_size / BDRV_SECTOR_SIZE;
38
- *cluster_sector_num = QEMU_ALIGN_DOWN(sector_num, c);
39
- *cluster_nb_sectors = QEMU_ALIGN_UP(sector_num - *cluster_sector_num +
40
- nb_sectors, c);
41
- }
42
-}
43
-
44
-/**
45
* Round a region to cluster boundaries
46
*/
47
void bdrv_round_to_clusters(BlockDriverState *bs,
48
diff --git a/include/block/block.h b/include/block/block.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block.h
51
+++ b/include/block/block.h
52
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
53
int bdrv_get_flags(BlockDriverState *bs);
54
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
55
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs);
56
-void bdrv_round_sectors_to_clusters(BlockDriverState *bs,
57
- int64_t sector_num, int nb_sectors,
58
- int64_t *cluster_sector_num,
59
- int *cluster_nb_sectors);
60
void bdrv_round_to_clusters(BlockDriverState *bs,
61
int64_t offset, unsigned int bytes,
62
int64_t *cluster_offset,
63
--
34
--
64
1.8.3.1
35
2.37.3
65
66
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Start by converting an
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
internal function (no semantic change).
5
functions where this holds.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Message-Id: <20220922084924.201610-14-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block/commit.c | 15 ++++++++-------
14
block/parallels.c | 5 +++--
14
1 file changed, 8 insertions(+), 7 deletions(-)
15
1 file changed, 3 insertions(+), 2 deletions(-)
15
16
16
diff --git a/block/commit.c b/block/commit.c
17
diff --git a/block/parallels.c b/block/parallels.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block/commit.c
19
--- a/block/parallels.c
19
+++ b/block/commit.c
20
+++ b/block/parallels.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct CommitBlockJob {
21
@@ -XXX,XX +XXX,XX @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
21
} CommitBlockJob;
22
return start_off;
22
23
}
23
static int coroutine_fn commit_populate(BlockBackend *bs, BlockBackend *base,
24
24
- int64_t sector_num, int nb_sectors,
25
-static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
25
+ int64_t offset, uint64_t bytes,
26
- int nb_sectors, int *pnum)
26
void *buf)
27
+static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
28
+ int64_t sector_num,
29
+ int nb_sectors, int *pnum)
27
{
30
{
28
int ret = 0;
31
int ret = 0;
29
QEMUIOVector qiov;
32
BDRVParallelsState *s = bs->opaque;
30
struct iovec iov = {
31
.iov_base = buf,
32
- .iov_len = nb_sectors * BDRV_SECTOR_SIZE,
33
+ .iov_len = bytes,
34
};
35
36
+ assert(bytes < SIZE_MAX);
37
qemu_iovec_init_external(&qiov, &iov, 1);
38
39
- ret = blk_co_preadv(bs, sector_num * BDRV_SECTOR_SIZE,
40
- qiov.size, &qiov, 0);
41
+ ret = blk_co_preadv(bs, offset, qiov.size, &qiov, 0);
42
if (ret < 0) {
43
return ret;
44
}
45
46
- ret = blk_co_pwritev(base, sector_num * BDRV_SECTOR_SIZE,
47
- qiov.size, &qiov, 0);
48
+ ret = blk_co_pwritev(base, offset, qiov.size, &qiov, 0);
49
if (ret < 0) {
50
return ret;
51
}
52
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
53
trace_commit_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
54
n * BDRV_SECTOR_SIZE, ret);
55
if (copy) {
56
- ret = commit_populate(s->top, s->base, sector_num, n, buf);
57
+ ret = commit_populate(s->top, s->base,
58
+ sector_num * BDRV_SECTOR_SIZE,
59
+ n * BDRV_SECTOR_SIZE, buf);
60
bytes_written += n * BDRV_SECTOR_SIZE;
61
}
62
if (ret < 0) {
63
--
33
--
64
1.8.3.1
34
2.37.3
65
66
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
This adds support for using LUKS as an encryption format
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
with the qcow2 file, using the new encrypt.format parameter
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
to request "luks" format. e.g.
5
functions where this holds.
6
6
7
# qemu-img create --object secret,data=123456,id=sec0 \
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
-f qcow2 -o encrypt.format=luks,encrypt.key-secret=sec0 \
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
test.qcow2 10G
9
Message-Id: <20220922084924.201610-15-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/qcow2.h | 15 ++++++++-------
15
block/qcow2-cluster.c | 21 ++++++++++++---------
16
block/qcow2-refcount.c | 2 +-
17
block/qcow2.c | 5 +++--
18
4 files changed, 24 insertions(+), 19 deletions(-)
10
19
11
The legacy "encryption=on" parameter still results in
20
diff --git a/block/qcow2.h b/block/qcow2.h
12
creation of the old qcow2 AES format (and is equivalent
21
index XXXXXXX..XXXXXXX 100644
13
to the new 'encryption-format=aes'). e.g. the following are
22
--- a/block/qcow2.h
14
equivalent:
23
+++ b/block/qcow2.h
15
24
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
16
# qemu-img create --object secret,data=123456,id=sec0 \
25
void *cb_opaque, Error **errp);
17
-f qcow2 -o encryption=on,encrypt.key-secret=sec0 \
26
int qcow2_shrink_reftable(BlockDriverState *bs);
18
test.qcow2 10G
27
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
19
28
-int qcow2_detect_metadata_preallocation(BlockDriverState *bs);
20
# qemu-img create --object secret,data=123456,id=sec0 \
29
+int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
21
-f qcow2 -o encryption-format=aes,encrypt.key-secret=sec0 \
30
22
test.qcow2 10G
31
/* qcow2-cluster.c functions */
23
32
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
24
With the LUKS format it is necessary to store the LUKS
33
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
25
partition header and key material in the QCow2 file. This
34
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
26
data can be many MB in size, so cannot go into the QCow2
35
unsigned int *bytes, uint64_t *host_offset,
27
header region directly. Thus the spec defines a FDE
36
QCow2SubclusterType *subcluster_type);
28
(Full Disk Encryption) header extension that specifies
37
-int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
29
the offset of a set of clusters to hold the FDE headers,
38
- unsigned int *bytes, uint64_t *host_offset,
30
as well as the length of that region. The LUKS header is
39
- QCowL2Meta **m);
31
thus stored in these extra allocated clusters before the
40
+int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
32
main image payload.
41
+ unsigned int *bytes,
33
42
+ uint64_t *host_offset, QCowL2Meta **m);
34
Aside from all the cryptographic differences implied by
43
int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
35
use of the LUKS format, there is one further key difference
44
uint64_t offset,
36
between the use of legacy AES and LUKS encryption in qcow2.
45
int compressed_size,
37
For LUKS, the initialiazation vectors are generated using
46
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
38
the host physical sector as the input, rather than the
47
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
39
guest virtual sector. This guarantees unique initialization
48
uint64_t *coffset, int *csize);
40
vectors for all sectors when qcow2 internal snapshots are
49
41
used, thus giving stronger protection against watermarking
50
-int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
42
attacks.
51
+int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
43
52
+ QCowL2Meta *m);
44
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
53
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
45
Message-id: 20170623162419.26068-14-berrange@redhat.com
54
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
46
Reviewed-by: Alberto Garcia <berto@igalia.com>
55
uint64_t bytes, enum qcow2_discard_type type,
47
Signed-off-by: Max Reitz <mreitz@redhat.com>
56
bool full_discard);
48
---
57
-int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
49
block/qcow2-cluster.c | 14 ++-
58
- uint64_t bytes, int flags);
50
block/qcow2-refcount.c | 10 ++
59
+int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
51
block/qcow2.c | 268 ++++++++++++++++++++++++++++++++++++++------
60
+ uint64_t bytes, int flags);
52
block/qcow2.h | 9 ++
61
53
qapi/block-core.json | 5 +-
62
int qcow2_expand_zero_clusters(BlockDriverState *bs,
54
tests/qemu-iotests/082.out | 270 ++++++++++++++++++++++++++++++++++++---------
63
BlockDriverAmendStatusCB *status_cb,
55
6 files changed, 484 insertions(+), 92 deletions(-)
56
57
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
64
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
58
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
59
--- a/block/qcow2-cluster.c
66
--- a/block/qcow2-cluster.c
60
+++ b/block/qcow2-cluster.c
67
+++ b/block/qcow2-cluster.c
61
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
68
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
62
69
return 0;
63
static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
70
}
64
uint64_t src_cluster_offset,
71
65
+ uint64_t cluster_offset,
72
-static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
66
unsigned offset_in_cluster,
73
+static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m)
67
uint8_t *buffer,
68
unsigned bytes)
69
{
74
{
70
if (bytes && bs->encrypted) {
75
BDRVQcow2State *s = bs->opaque;
71
BDRVQcow2State *s = bs->opaque;
76
Qcow2COWRegion *start = &m->cow_start;
72
- int64_t sector = (src_cluster_offset + offset_in_cluster)
77
@@ -XXX,XX +XXX,XX @@ fail:
73
+ int64_t sector = (s->crypt_physical_offset ?
78
return ret;
74
+ (cluster_offset + offset_in_cluster) :
79
}
75
+ (src_cluster_offset + offset_in_cluster))
80
76
>> BDRV_SECTOR_BITS;
81
-int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
77
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
82
+int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs,
78
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
83
+ QCowL2Meta *m)
79
@@ -XXX,XX +XXX,XX @@ static int perform_cow(BlockDriverState *bs, QCowL2Meta *m)
84
{
80
85
BDRVQcow2State *s = bs->opaque;
81
/* Encrypt the data if necessary before writing it */
86
int i, j = 0, l2_index, ret;
82
if (bs->encrypted) {
87
@@ -XXX,XX +XXX,XX @@ static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters,
83
- if (!do_perform_cow_encrypt(bs, m->offset, start->offset,
88
* information on cluster allocation may be invalid now. The caller
84
- start_buffer, start->nb_bytes) ||
89
* must start over anyway, so consider *cur_bytes undefined.
85
- !do_perform_cow_encrypt(bs, m->offset, end->offset,
90
*/
86
- end_buffer, end->nb_bytes)) {
91
-static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
87
+ if (!do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
92
- uint64_t *cur_bytes, QCowL2Meta **m)
88
+ start->offset, start_buffer,
93
+static int coroutine_fn handle_dependencies(BlockDriverState *bs,
89
+ start->nb_bytes) ||
94
+ uint64_t guest_offset,
90
+ !do_perform_cow_encrypt(bs, m->offset, m->alloc_offset,
95
+ uint64_t *cur_bytes, QCowL2Meta **m)
91
+ end->offset, end_buffer, end->nb_bytes)) {
96
{
92
ret = -EIO;
97
BDRVQcow2State *s = bs->opaque;
93
goto fail;
98
QCowL2Meta *old_alloc;
94
}
99
@@ -XXX,XX +XXX,XX @@ out:
100
*
101
* Return 0 on success and -errno in error cases
102
*/
103
-int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
104
- unsigned int *bytes, uint64_t *host_offset,
105
- QCowL2Meta **m)
106
+int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
107
+ unsigned int *bytes,
108
+ uint64_t *host_offset,
109
+ QCowL2Meta **m)
110
{
111
BDRVQcow2State *s = bs->opaque;
112
uint64_t start, remaining;
113
@@ -XXX,XX +XXX,XX @@ out:
114
return ret;
115
}
116
117
-int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
118
- uint64_t bytes, int flags)
119
+int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
120
+ uint64_t bytes, int flags)
121
{
122
BDRVQcow2State *s = bs->opaque;
123
uint64_t end_offset = offset + bytes;
95
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
124
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
96
index XXXXXXX..XXXXXXX 100644
125
index XXXXXXX..XXXXXXX 100644
97
--- a/block/qcow2-refcount.c
126
--- a/block/qcow2-refcount.c
98
+++ b/block/qcow2-refcount.c
127
+++ b/block/qcow2-refcount.c
99
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
128
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
100
return ret;
129
return -EIO;
101
}
102
103
+ /* encryption */
104
+ if (s->crypto_header.length) {
105
+ ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
106
+ s->crypto_header.offset,
107
+ s->crypto_header.length);
108
+ if (ret < 0) {
109
+ return ret;
110
+ }
111
+ }
112
+
113
return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters);
114
}
130
}
115
131
132
-int qcow2_detect_metadata_preallocation(BlockDriverState *bs)
133
+int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
134
{
135
BDRVQcow2State *s = bs->opaque;
136
int64_t i, end_cluster, cluster_count = 0, threshold;
116
diff --git a/block/qcow2.c b/block/qcow2.c
137
diff --git a/block/qcow2.c b/block/qcow2.c
117
index XXXXXXX..XXXXXXX 100644
138
index XXXXXXX..XXXXXXX 100644
118
--- a/block/qcow2.c
139
--- a/block/qcow2.c
119
+++ b/block/qcow2.c
140
+++ b/block/qcow2.c
120
@@ -XXX,XX +XXX,XX @@ typedef struct {
141
@@ -XXX,XX +XXX,XX @@ static bool merge_cow(uint64_t offset, unsigned bytes,
121
#define QCOW2_EXT_MAGIC_END 0
142
* Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error.
122
#define QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
143
* Note that returning 0 does not guarantee non-zero data.
123
#define QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857
144
*/
124
+#define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77
145
-static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
125
146
+static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
126
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
127
{
147
{
128
@@ -XXX,XX +XXX,XX @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
148
/*
149
* This check is designed for optimization shortcut so it must be
150
@@ -XXX,XX +XXX,XX @@ static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
151
m->cow_end.nb_bytes);
129
}
152
}
130
153
131
154
-static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
132
+static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
155
+static int coroutine_fn handle_alloc_space(BlockDriverState *bs,
133
+ uint8_t *buf, size_t buflen,
156
+ QCowL2Meta *l2meta)
134
+ void *opaque, Error **errp)
135
+{
136
+ BlockDriverState *bs = opaque;
137
+ BDRVQcow2State *s = bs->opaque;
138
+ ssize_t ret;
139
+
140
+ if ((offset + buflen) > s->crypto_header.length) {
141
+ error_setg(errp, "Request for data outside of extension header");
142
+ return -1;
143
+ }
144
+
145
+ ret = bdrv_pread(bs->file,
146
+ s->crypto_header.offset + offset, buf, buflen);
147
+ if (ret < 0) {
148
+ error_setg_errno(errp, -ret, "Could not read encryption header");
149
+ return -1;
150
+ }
151
+ return ret;
152
+}
153
+
154
+
155
+static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
156
+ void *opaque, Error **errp)
157
+{
158
+ BlockDriverState *bs = opaque;
159
+ BDRVQcow2State *s = bs->opaque;
160
+ int64_t ret;
161
+ int64_t clusterlen;
162
+
163
+ ret = qcow2_alloc_clusters(bs, headerlen);
164
+ if (ret < 0) {
165
+ error_setg_errno(errp, -ret,
166
+ "Cannot allocate cluster for LUKS header size %zu",
167
+ headerlen);
168
+ return -1;
169
+ }
170
+
171
+ s->crypto_header.length = headerlen;
172
+ s->crypto_header.offset = ret;
173
+
174
+ /* Zero fill remaining space in cluster so it has predictable
175
+ * content in case of future spec changes */
176
+ clusterlen = size_to_clusters(s, headerlen) * s->cluster_size;
177
+ ret = bdrv_pwrite_zeroes(bs->file,
178
+ ret + headerlen,
179
+ clusterlen - headerlen, 0);
180
+ if (ret < 0) {
181
+ error_setg_errno(errp, -ret, "Could not zero fill encryption header");
182
+ return -1;
183
+ }
184
+
185
+ return ret;
186
+}
187
+
188
+
189
+static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
190
+ const uint8_t *buf, size_t buflen,
191
+ void *opaque, Error **errp)
192
+{
193
+ BlockDriverState *bs = opaque;
194
+ BDRVQcow2State *s = bs->opaque;
195
+ ssize_t ret;
196
+
197
+ if ((offset + buflen) > s->crypto_header.length) {
198
+ error_setg(errp, "Request for data outside of extension header");
199
+ return -1;
200
+ }
201
+
202
+ ret = bdrv_pwrite(bs->file,
203
+ s->crypto_header.offset + offset, buf, buflen);
204
+ if (ret < 0) {
205
+ error_setg_errno(errp, -ret, "Could not read encryption header");
206
+ return -1;
207
+ }
208
+ return ret;
209
+}
210
+
211
+
212
/*
213
* read qcow2 extension and fill bs
214
* start reading from start_offset
215
@@ -XXX,XX +XXX,XX @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
216
*/
217
static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
218
uint64_t end_offset, void **p_feature_table,
219
- Error **errp)
220
+ int flags, Error **errp)
221
{
157
{
222
BDRVQcow2State *s = bs->opaque;
158
BDRVQcow2State *s = bs->opaque;
223
QCowExtension ext;
159
QCowL2Meta *m;
224
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
225
}
226
break;
227
228
+ case QCOW2_EXT_MAGIC_CRYPTO_HEADER: {
229
+ unsigned int cflags = 0;
230
+ if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
231
+ error_setg(errp, "CRYPTO header extension only "
232
+ "expected with LUKS encryption method");
233
+ return -EINVAL;
234
+ }
235
+ if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) {
236
+ error_setg(errp, "CRYPTO header extension size %u, "
237
+ "but expected size %zu", ext.len,
238
+ sizeof(Qcow2CryptoHeaderExtension));
239
+ return -EINVAL;
240
+ }
241
+
242
+ ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len);
243
+ if (ret < 0) {
244
+ error_setg_errno(errp, -ret,
245
+ "Unable to read CRYPTO header extension");
246
+ return ret;
247
+ }
248
+ be64_to_cpus(&s->crypto_header.offset);
249
+ be64_to_cpus(&s->crypto_header.length);
250
+
251
+ if ((s->crypto_header.offset % s->cluster_size) != 0) {
252
+ error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
253
+ "not a multiple of cluster size '%u'",
254
+ s->crypto_header.offset, s->cluster_size);
255
+ return -EINVAL;
256
+ }
257
+
258
+ if (flags & BDRV_O_NO_IO) {
259
+ cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
260
+ }
261
+ s->crypto = qcrypto_block_open(s->crypto_opts,
262
+ qcow2_crypto_hdr_read_func,
263
+ bs, cflags, errp);
264
+ if (!s->crypto) {
265
+ return -EINVAL;
266
+ }
267
+ } break;
268
+
269
default:
270
/* unknown magic - save it in case we need to rewrite the header */
271
{
272
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_runtime_opts = {
273
.type = QEMU_OPT_NUMBER,
274
.help = "Clean unused cache entries after this time (in seconds)",
275
},
276
- BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
277
+ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.",
278
+ "ID of secret providing qcow2 AES key or LUKS passphrase"),
279
{ /* end of list */ }
280
},
281
};
282
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
283
Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
284
break;
285
286
+ case QCOW_CRYPT_LUKS:
287
+ if (encryptfmt && !g_str_equal(encryptfmt, "luks")) {
288
+ error_setg(errp,
289
+ "Header reported 'luks' encryption format but "
290
+ "options specify '%s'", encryptfmt);
291
+ ret = -EINVAL;
292
+ goto fail;
293
+ }
294
+ qdict_del(encryptopts, "format");
295
+ r->crypto_opts = block_crypto_open_opts_init(
296
+ Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp);
297
+ break;
298
+
299
default:
300
error_setg(errp, "Unsupported encryption method %d",
301
s->crypt_method_header);
302
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
303
if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
304
void *feature_table = NULL;
305
qcow2_read_extensions(bs, header.header_length, ext_end,
306
- &feature_table, NULL);
307
+ &feature_table, flags, NULL);
308
report_unsupported_feature(errp, feature_table,
309
s->incompatible_features &
310
~QCOW2_INCOMPAT_MASK);
311
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
312
s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1);
313
s->refcount_max += s->refcount_max - 1;
314
315
- if (header.crypt_method > QCOW_CRYPT_AES) {
316
- error_setg(errp, "Unsupported encryption method: %" PRIu32,
317
- header.crypt_method);
318
- ret = -EINVAL;
319
- goto fail;
320
- }
321
s->crypt_method_header = header.crypt_method;
322
if (s->crypt_method_header) {
323
if (bdrv_uses_whitelist() &&
324
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
325
goto fail;
326
}
327
328
+ if (s->crypt_method_header == QCOW_CRYPT_AES) {
329
+ s->crypt_physical_offset = false;
330
+ } else {
331
+ /* Assuming LUKS and any future crypt methods we
332
+ * add will all use physical offsets, due to the
333
+ * fact that the alternative is insecure... */
334
+ s->crypt_physical_offset = true;
335
+ }
336
+
337
bs->encrypted = true;
338
bs->valid_key = true;
339
}
340
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
341
342
/* read qcow2 extensions */
343
if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL,
344
- &local_err)) {
345
+ flags, &local_err)) {
346
error_propagate(errp, local_err);
347
ret = -EINVAL;
348
goto fail;
349
}
350
351
- if (s->crypt_method_header == QCOW_CRYPT_AES) {
352
- unsigned int cflags = 0;
353
- if (flags & BDRV_O_NO_IO) {
354
- cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
355
- }
356
- s->crypto = qcrypto_block_open(s->crypto_opts, NULL, NULL,
357
- cflags, errp);
358
- if (!s->crypto) {
359
+ /* qcow2_read_extension may have set up the crypto context
360
+ * if the crypt method needs a header region, some methods
361
+ * don't need header extensions, so must check here
362
+ */
363
+ if (s->crypt_method_header && !s->crypto) {
364
+ if (s->crypt_method_header == QCOW_CRYPT_AES) {
365
+ unsigned int cflags = 0;
366
+ if (flags & BDRV_O_NO_IO) {
367
+ cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
368
+ }
369
+ s->crypto = qcrypto_block_open(s->crypto_opts, NULL, NULL,
370
+ cflags, errp);
371
+ if (!s->crypto) {
372
+ ret = -EINVAL;
373
+ goto fail;
374
+ }
375
+ } else if (!(flags & BDRV_O_NO_IO)) {
376
+ error_setg(errp, "Missing CRYPTO header for crypt method %d",
377
+ s->crypt_method_header);
378
ret = -EINVAL;
379
goto fail;
380
}
381
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
382
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
383
Error *err = NULL;
384
if (qcrypto_block_decrypt(s->crypto,
385
- offset >> BDRV_SECTOR_BITS,
386
+ (s->crypt_physical_offset ?
387
+ cluster_offset + offset_in_cluster :
388
+ offset) >> BDRV_SECTOR_BITS,
389
cluster_data,
390
cur_bytes,
391
&err) < 0) {
392
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
393
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
394
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
395
396
- if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,
397
+ if (qcrypto_block_encrypt(s->crypto,
398
+ (s->crypt_physical_offset ?
399
+ cluster_offset + offset_in_cluster :
400
+ offset) >> BDRV_SECTOR_BITS,
401
cluster_data,
402
cur_bytes, &err) < 0) {
403
error_free(err);
404
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
405
buflen -= ret;
406
}
407
408
+ /* Full disk encryption header pointer extension */
409
+ if (s->crypto_header.offset != 0) {
410
+ cpu_to_be64s(&s->crypto_header.offset);
411
+ cpu_to_be64s(&s->crypto_header.length);
412
+ ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
413
+ &s->crypto_header, sizeof(s->crypto_header),
414
+ buflen);
415
+ be64_to_cpus(&s->crypto_header.offset);
416
+ be64_to_cpus(&s->crypto_header.length);
417
+ if (ret < 0) {
418
+ goto fail;
419
+ }
420
+ buf += ret;
421
+ buflen -= ret;
422
+ }
423
+
424
/* Feature table */
425
if (s->qcow_version >= 3) {
426
Qcow2Feature features[] = {
427
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
428
return qcow2_update_header(bs);
429
}
430
431
+static int qcow2_crypt_method_from_format(const char *encryptfmt)
432
+{
433
+ if (g_str_equal(encryptfmt, "luks")) {
434
+ return QCOW_CRYPT_LUKS;
435
+ } else if (g_str_equal(encryptfmt, "aes")) {
436
+ return QCOW_CRYPT_AES;
437
+ } else {
438
+ return -EINVAL;
439
+ }
440
+}
441
442
static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
443
QemuOpts *opts, Error **errp)
444
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
445
QCryptoBlock *crypto = NULL;
446
int ret = -EINVAL;
447
QDict *options, *encryptopts;
448
+ int fmt;
449
450
options = qemu_opts_to_qdict(opts, NULL);
451
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
452
QDECREF(options);
453
454
- if (!g_str_equal(encryptfmt, "aes")) {
455
- error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
456
- encryptfmt);
457
- ret = -EINVAL;
458
- goto out;
459
+ fmt = qcow2_crypt_method_from_format(encryptfmt);
460
+
461
+ switch (fmt) {
462
+ case QCOW_CRYPT_LUKS:
463
+ cryptoopts = block_crypto_create_opts_init(
464
+ Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp);
465
+ break;
466
+ case QCOW_CRYPT_AES:
467
+ cryptoopts = block_crypto_create_opts_init(
468
+ Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
469
+ break;
470
+ default:
471
+ error_setg(errp, "Unknown encryption format '%s'", encryptfmt);
472
+ break;
473
}
474
- cryptoopts = block_crypto_create_opts_init(
475
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
476
if (!cryptoopts) {
477
ret = -EINVAL;
478
goto out;
479
}
480
- s->crypt_method_header = QCOW_CRYPT_AES;
481
+ s->crypt_method_header = fmt;
482
483
crypto = qcrypto_block_create(cryptoopts,
484
- NULL, NULL,
485
+ qcow2_crypto_hdr_init_func,
486
+ qcow2_crypto_hdr_write_func,
487
bs, errp);
488
if (!crypto) {
489
ret = -EINVAL;
490
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
491
const char *compat = NULL;
492
uint64_t cluster_size = s->cluster_size;
493
bool encrypt;
494
+ int encformat;
495
int refcount_bits = s->refcount_bits;
496
Error *local_err = NULL;
497
int ret;
498
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
499
error_report("Changing the encryption flag is not supported");
500
return -ENOTSUP;
501
}
502
+ } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) {
503
+ encformat = qcow2_crypt_method_from_format(
504
+ qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT));
505
+
506
+ if (encformat != s->crypt_method_header) {
507
+ error_report("Changing the encryption format is not supported");
508
+ return -ENOTSUP;
509
+ }
510
} else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
511
cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
512
cluster_size);
513
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
514
{
515
.name = BLOCK_OPT_ENCRYPT_FORMAT,
516
.type = QEMU_OPT_STRING,
517
- .help = "Encrypt the image, format choices: 'aes'",
518
+ .help = "Encrypt the image, format choices: 'aes', 'luks'",
519
},
520
- BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
521
+ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.",
522
+ "ID of secret providing qcow AES key or LUKS passphrase"),
523
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."),
524
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."),
525
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."),
526
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."),
527
+ BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."),
528
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."),
529
{
530
.name = BLOCK_OPT_CLUSTER_SIZE,
531
.type = QEMU_OPT_SIZE,
532
diff --git a/block/qcow2.h b/block/qcow2.h
533
index XXXXXXX..XXXXXXX 100644
534
--- a/block/qcow2.h
535
+++ b/block/qcow2.h
536
@@ -XXX,XX +XXX,XX @@
537
538
#define QCOW_CRYPT_NONE 0
539
#define QCOW_CRYPT_AES 1
540
+#define QCOW_CRYPT_LUKS 2
541
542
#define QCOW_MAX_CRYPT_CLUSTERS 32
543
#define QCOW_MAX_SNAPSHOTS 65536
544
@@ -XXX,XX +XXX,XX @@ typedef struct QCowSnapshot {
545
struct Qcow2Cache;
546
typedef struct Qcow2Cache Qcow2Cache;
547
548
+typedef struct Qcow2CryptoHeaderExtension {
549
+ uint64_t offset;
550
+ uint64_t length;
551
+} QEMU_PACKED Qcow2CryptoHeaderExtension;
552
+
553
typedef struct Qcow2UnknownHeaderExtension {
554
uint32_t magic;
555
uint32_t len;
556
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
557
558
CoMutex lock;
559
560
+ Qcow2CryptoHeaderExtension crypto_header; /* QCow2 header extension */
561
QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
562
QCryptoBlock *crypto; /* Disk encryption format driver */
563
+ bool crypt_physical_offset; /* Whether to use virtual or physical offset
564
+ for encryption initialization vector tweak */
565
uint32_t crypt_method_header;
566
uint64_t snapshots_offset;
567
int snapshots_size;
568
diff --git a/qapi/block-core.json b/qapi/block-core.json
569
index XXXXXXX..XXXXXXX 100644
570
--- a/qapi/block-core.json
571
+++ b/qapi/block-core.json
572
@@ -XXX,XX +XXX,XX @@
573
# Since: 2.10
574
##
575
{ 'enum': 'BlockdevQcow2EncryptionFormat',
576
- 'data': [ 'aes' ] }
577
+ 'data': [ 'aes', 'luks' ] }
578
579
##
580
# @BlockdevQcow2Encryption:
581
@@ -XXX,XX +XXX,XX @@
582
{ 'union': 'BlockdevQcow2Encryption',
583
'base': { 'format': 'BlockdevQcow2EncryptionFormat' },
584
'discriminator': 'format',
585
- 'data': { 'aes': 'QCryptoBlockOptionsQCow' } }
586
+ 'data': { 'aes': 'QCryptoBlockOptionsQCow',
587
+ 'luks': 'QCryptoBlockOptionsLUKS'} }
588
589
##
590
# @BlockdevOptionsQcow2:
591
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
592
index XXXXXXX..XXXXXXX 100644
593
--- a/tests/qemu-iotests/082.out
594
+++ b/tests/qemu-iotests/082.out
595
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
596
backing_file File name of a base image
597
backing_fmt Image format of the base image
598
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
599
-encrypt.format Encrypt the image, format choices: 'aes'
600
-encrypt.key-secret ID of the secret that provides the AES encryption key
601
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
602
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
603
+encrypt.cipher-alg Name of encryption cipher algorithm
604
+encrypt.cipher-mode Name of encryption cipher mode
605
+encrypt.ivgen-alg Name of IV generator algorithm
606
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
607
+encrypt.hash-alg Name of encryption hash algorithm
608
+encrypt.iter-time Time to spend in PBKDF in milliseconds
609
cluster_size qcow2 cluster size
610
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
611
lazy_refcounts Postpone refcount updates
612
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
613
backing_file File name of a base image
614
backing_fmt Image format of the base image
615
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
616
-encrypt.format Encrypt the image, format choices: 'aes'
617
-encrypt.key-secret ID of the secret that provides the AES encryption key
618
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
619
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
620
+encrypt.cipher-alg Name of encryption cipher algorithm
621
+encrypt.cipher-mode Name of encryption cipher mode
622
+encrypt.ivgen-alg Name of IV generator algorithm
623
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
624
+encrypt.hash-alg Name of encryption hash algorithm
625
+encrypt.iter-time Time to spend in PBKDF in milliseconds
626
cluster_size qcow2 cluster size
627
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
628
lazy_refcounts Postpone refcount updates
629
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
630
backing_file File name of a base image
631
backing_fmt Image format of the base image
632
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
633
-encrypt.format Encrypt the image, format choices: 'aes'
634
-encrypt.key-secret ID of the secret that provides the AES encryption key
635
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
636
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
637
+encrypt.cipher-alg Name of encryption cipher algorithm
638
+encrypt.cipher-mode Name of encryption cipher mode
639
+encrypt.ivgen-alg Name of IV generator algorithm
640
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
641
+encrypt.hash-alg Name of encryption hash algorithm
642
+encrypt.iter-time Time to spend in PBKDF in milliseconds
643
cluster_size qcow2 cluster size
644
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
645
lazy_refcounts Postpone refcount updates
646
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
647
backing_file File name of a base image
648
backing_fmt Image format of the base image
649
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
650
-encrypt.format Encrypt the image, format choices: 'aes'
651
-encrypt.key-secret ID of the secret that provides the AES encryption key
652
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
653
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
654
+encrypt.cipher-alg Name of encryption cipher algorithm
655
+encrypt.cipher-mode Name of encryption cipher mode
656
+encrypt.ivgen-alg Name of IV generator algorithm
657
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
658
+encrypt.hash-alg Name of encryption hash algorithm
659
+encrypt.iter-time Time to spend in PBKDF in milliseconds
660
cluster_size qcow2 cluster size
661
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
662
lazy_refcounts Postpone refcount updates
663
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
664
backing_file File name of a base image
665
backing_fmt Image format of the base image
666
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
667
-encrypt.format Encrypt the image, format choices: 'aes'
668
-encrypt.key-secret ID of the secret that provides the AES encryption key
669
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
670
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
671
+encrypt.cipher-alg Name of encryption cipher algorithm
672
+encrypt.cipher-mode Name of encryption cipher mode
673
+encrypt.ivgen-alg Name of IV generator algorithm
674
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
675
+encrypt.hash-alg Name of encryption hash algorithm
676
+encrypt.iter-time Time to spend in PBKDF in milliseconds
677
cluster_size qcow2 cluster size
678
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
679
lazy_refcounts Postpone refcount updates
680
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
681
backing_file File name of a base image
682
backing_fmt Image format of the base image
683
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
684
-encrypt.format Encrypt the image, format choices: 'aes'
685
-encrypt.key-secret ID of the secret that provides the AES encryption key
686
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
687
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
688
+encrypt.cipher-alg Name of encryption cipher algorithm
689
+encrypt.cipher-mode Name of encryption cipher mode
690
+encrypt.ivgen-alg Name of IV generator algorithm
691
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
692
+encrypt.hash-alg Name of encryption hash algorithm
693
+encrypt.iter-time Time to spend in PBKDF in milliseconds
694
cluster_size qcow2 cluster size
695
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
696
lazy_refcounts Postpone refcount updates
697
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
698
backing_file File name of a base image
699
backing_fmt Image format of the base image
700
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
701
-encrypt.format Encrypt the image, format choices: 'aes'
702
-encrypt.key-secret ID of the secret that provides the AES encryption key
703
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
704
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
705
+encrypt.cipher-alg Name of encryption cipher algorithm
706
+encrypt.cipher-mode Name of encryption cipher mode
707
+encrypt.ivgen-alg Name of IV generator algorithm
708
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
709
+encrypt.hash-alg Name of encryption hash algorithm
710
+encrypt.iter-time Time to spend in PBKDF in milliseconds
711
cluster_size qcow2 cluster size
712
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
713
lazy_refcounts Postpone refcount updates
714
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
715
backing_file File name of a base image
716
backing_fmt Image format of the base image
717
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
718
-encrypt.format Encrypt the image, format choices: 'aes'
719
-encrypt.key-secret ID of the secret that provides the AES encryption key
720
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
721
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
722
+encrypt.cipher-alg Name of encryption cipher algorithm
723
+encrypt.cipher-mode Name of encryption cipher mode
724
+encrypt.ivgen-alg Name of IV generator algorithm
725
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
726
+encrypt.hash-alg Name of encryption hash algorithm
727
+encrypt.iter-time Time to spend in PBKDF in milliseconds
728
cluster_size qcow2 cluster size
729
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
730
lazy_refcounts Postpone refcount updates
731
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
732
backing_file File name of a base image
733
backing_fmt Image format of the base image
734
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
735
-encrypt.format Encrypt the image, format choices: 'aes'
736
-encrypt.key-secret ID of the secret that provides the AES encryption key
737
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
738
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
739
+encrypt.cipher-alg Name of encryption cipher algorithm
740
+encrypt.cipher-mode Name of encryption cipher mode
741
+encrypt.ivgen-alg Name of IV generator algorithm
742
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
743
+encrypt.hash-alg Name of encryption hash algorithm
744
+encrypt.iter-time Time to spend in PBKDF in milliseconds
745
cluster_size qcow2 cluster size
746
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
747
lazy_refcounts Postpone refcount updates
748
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
749
backing_file File name of a base image
750
backing_fmt Image format of the base image
751
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
752
-encrypt.format Encrypt the image, format choices: 'aes'
753
-encrypt.key-secret ID of the secret that provides the AES encryption key
754
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
755
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
756
+encrypt.cipher-alg Name of encryption cipher algorithm
757
+encrypt.cipher-mode Name of encryption cipher mode
758
+encrypt.ivgen-alg Name of IV generator algorithm
759
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
760
+encrypt.hash-alg Name of encryption hash algorithm
761
+encrypt.iter-time Time to spend in PBKDF in milliseconds
762
cluster_size qcow2 cluster size
763
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
764
lazy_refcounts Postpone refcount updates
765
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
766
backing_file File name of a base image
767
backing_fmt Image format of the base image
768
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
769
-encrypt.format Encrypt the image, format choices: 'aes'
770
-encrypt.key-secret ID of the secret that provides the AES encryption key
771
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
772
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
773
+encrypt.cipher-alg Name of encryption cipher algorithm
774
+encrypt.cipher-mode Name of encryption cipher mode
775
+encrypt.ivgen-alg Name of IV generator algorithm
776
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
777
+encrypt.hash-alg Name of encryption hash algorithm
778
+encrypt.iter-time Time to spend in PBKDF in milliseconds
779
cluster_size qcow2 cluster size
780
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
781
lazy_refcounts Postpone refcount updates
782
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
783
backing_file File name of a base image
784
backing_fmt Image format of the base image
785
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
786
-encrypt.format Encrypt the image, format choices: 'aes'
787
-encrypt.key-secret ID of the secret that provides the AES encryption key
788
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
789
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
790
+encrypt.cipher-alg Name of encryption cipher algorithm
791
+encrypt.cipher-mode Name of encryption cipher mode
792
+encrypt.ivgen-alg Name of IV generator algorithm
793
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
794
+encrypt.hash-alg Name of encryption hash algorithm
795
+encrypt.iter-time Time to spend in PBKDF in milliseconds
796
cluster_size qcow2 cluster size
797
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
798
lazy_refcounts Postpone refcount updates
799
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
800
backing_file File name of a base image
801
backing_fmt Image format of the base image
802
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
803
-encrypt.format Encrypt the image, format choices: 'aes'
804
-encrypt.key-secret ID of the secret that provides the AES encryption key
805
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
806
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
807
+encrypt.cipher-alg Name of encryption cipher algorithm
808
+encrypt.cipher-mode Name of encryption cipher mode
809
+encrypt.ivgen-alg Name of IV generator algorithm
810
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
811
+encrypt.hash-alg Name of encryption hash algorithm
812
+encrypt.iter-time Time to spend in PBKDF in milliseconds
813
cluster_size qcow2 cluster size
814
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
815
lazy_refcounts Postpone refcount updates
816
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
817
backing_file File name of a base image
818
backing_fmt Image format of the base image
819
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
820
-encrypt.format Encrypt the image, format choices: 'aes'
821
-encrypt.key-secret ID of the secret that provides the AES encryption key
822
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
823
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
824
+encrypt.cipher-alg Name of encryption cipher algorithm
825
+encrypt.cipher-mode Name of encryption cipher mode
826
+encrypt.ivgen-alg Name of IV generator algorithm
827
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
828
+encrypt.hash-alg Name of encryption hash algorithm
829
+encrypt.iter-time Time to spend in PBKDF in milliseconds
830
cluster_size qcow2 cluster size
831
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
832
lazy_refcounts Postpone refcount updates
833
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
834
backing_file File name of a base image
835
backing_fmt Image format of the base image
836
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
837
-encrypt.format Encrypt the image, format choices: 'aes'
838
-encrypt.key-secret ID of the secret that provides the AES encryption key
839
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
840
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
841
+encrypt.cipher-alg Name of encryption cipher algorithm
842
+encrypt.cipher-mode Name of encryption cipher mode
843
+encrypt.ivgen-alg Name of IV generator algorithm
844
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
845
+encrypt.hash-alg Name of encryption hash algorithm
846
+encrypt.iter-time Time to spend in PBKDF in milliseconds
847
cluster_size qcow2 cluster size
848
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
849
lazy_refcounts Postpone refcount updates
850
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
851
backing_file File name of a base image
852
backing_fmt Image format of the base image
853
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
854
-encrypt.format Encrypt the image, format choices: 'aes'
855
-encrypt.key-secret ID of the secret that provides the AES encryption key
856
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
857
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
858
+encrypt.cipher-alg Name of encryption cipher algorithm
859
+encrypt.cipher-mode Name of encryption cipher mode
860
+encrypt.ivgen-alg Name of IV generator algorithm
861
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
862
+encrypt.hash-alg Name of encryption hash algorithm
863
+encrypt.iter-time Time to spend in PBKDF in milliseconds
864
cluster_size qcow2 cluster size
865
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
866
lazy_refcounts Postpone refcount updates
867
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
868
backing_file File name of a base image
869
backing_fmt Image format of the base image
870
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
871
-encrypt.format Encrypt the image, format choices: 'aes'
872
-encrypt.key-secret ID of the secret that provides the AES encryption key
873
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
874
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
875
+encrypt.cipher-alg Name of encryption cipher algorithm
876
+encrypt.cipher-mode Name of encryption cipher mode
877
+encrypt.ivgen-alg Name of IV generator algorithm
878
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
879
+encrypt.hash-alg Name of encryption hash algorithm
880
+encrypt.iter-time Time to spend in PBKDF in milliseconds
881
cluster_size qcow2 cluster size
882
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
883
lazy_refcounts Postpone refcount updates
884
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
885
backing_file File name of a base image
886
backing_fmt Image format of the base image
887
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
888
-encrypt.format Encrypt the image, format choices: 'aes'
889
-encrypt.key-secret ID of the secret that provides the AES encryption key
890
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
891
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
892
+encrypt.cipher-alg Name of encryption cipher algorithm
893
+encrypt.cipher-mode Name of encryption cipher mode
894
+encrypt.ivgen-alg Name of IV generator algorithm
895
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
896
+encrypt.hash-alg Name of encryption hash algorithm
897
+encrypt.iter-time Time to spend in PBKDF in milliseconds
898
cluster_size qcow2 cluster size
899
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
900
lazy_refcounts Postpone refcount updates
901
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
902
backing_file File name of a base image
903
backing_fmt Image format of the base image
904
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
905
-encrypt.format Encrypt the image, format choices: 'aes'
906
-encrypt.key-secret ID of the secret that provides the AES encryption key
907
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
908
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
909
+encrypt.cipher-alg Name of encryption cipher algorithm
910
+encrypt.cipher-mode Name of encryption cipher mode
911
+encrypt.ivgen-alg Name of IV generator algorithm
912
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
913
+encrypt.hash-alg Name of encryption hash algorithm
914
+encrypt.iter-time Time to spend in PBKDF in milliseconds
915
cluster_size qcow2 cluster size
916
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
917
lazy_refcounts Postpone refcount updates
918
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
919
backing_file File name of a base image
920
backing_fmt Image format of the base image
921
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
922
-encrypt.format Encrypt the image, format choices: 'aes'
923
-encrypt.key-secret ID of the secret that provides the AES encryption key
924
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
925
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
926
+encrypt.cipher-alg Name of encryption cipher algorithm
927
+encrypt.cipher-mode Name of encryption cipher mode
928
+encrypt.ivgen-alg Name of IV generator algorithm
929
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
930
+encrypt.hash-alg Name of encryption hash algorithm
931
+encrypt.iter-time Time to spend in PBKDF in milliseconds
932
cluster_size qcow2 cluster size
933
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
934
lazy_refcounts Postpone refcount updates
935
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
936
backing_file File name of a base image
937
backing_fmt Image format of the base image
938
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
939
-encrypt.format Encrypt the image, format choices: 'aes'
940
-encrypt.key-secret ID of the secret that provides the AES encryption key
941
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
942
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
943
+encrypt.cipher-alg Name of encryption cipher algorithm
944
+encrypt.cipher-mode Name of encryption cipher mode
945
+encrypt.ivgen-alg Name of IV generator algorithm
946
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
947
+encrypt.hash-alg Name of encryption hash algorithm
948
+encrypt.iter-time Time to spend in PBKDF in milliseconds
949
cluster_size qcow2 cluster size
950
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
951
lazy_refcounts Postpone refcount updates
952
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
953
backing_file File name of a base image
954
backing_fmt Image format of the base image
955
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
956
-encrypt.format Encrypt the image, format choices: 'aes'
957
-encrypt.key-secret ID of the secret that provides the AES encryption key
958
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
959
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
960
+encrypt.cipher-alg Name of encryption cipher algorithm
961
+encrypt.cipher-mode Name of encryption cipher mode
962
+encrypt.ivgen-alg Name of IV generator algorithm
963
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
964
+encrypt.hash-alg Name of encryption hash algorithm
965
+encrypt.iter-time Time to spend in PBKDF in milliseconds
966
cluster_size qcow2 cluster size
967
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
968
lazy_refcounts Postpone refcount updates
969
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
970
backing_file File name of a base image
971
backing_fmt Image format of the base image
972
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
973
-encrypt.format Encrypt the image, format choices: 'aes'
974
-encrypt.key-secret ID of the secret that provides the AES encryption key
975
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
976
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
977
+encrypt.cipher-alg Name of encryption cipher algorithm
978
+encrypt.cipher-mode Name of encryption cipher mode
979
+encrypt.ivgen-alg Name of IV generator algorithm
980
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
981
+encrypt.hash-alg Name of encryption hash algorithm
982
+encrypt.iter-time Time to spend in PBKDF in milliseconds
983
cluster_size qcow2 cluster size
984
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
985
lazy_refcounts Postpone refcount updates
986
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
987
backing_file File name of a base image
988
backing_fmt Image format of the base image
989
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
990
-encrypt.format Encrypt the image, format choices: 'aes'
991
-encrypt.key-secret ID of the secret that provides the AES encryption key
992
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
993
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
994
+encrypt.cipher-alg Name of encryption cipher algorithm
995
+encrypt.cipher-mode Name of encryption cipher mode
996
+encrypt.ivgen-alg Name of IV generator algorithm
997
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
998
+encrypt.hash-alg Name of encryption hash algorithm
999
+encrypt.iter-time Time to spend in PBKDF in milliseconds
1000
cluster_size qcow2 cluster size
1001
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1002
lazy_refcounts Postpone refcount updates
1003
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
1004
backing_file File name of a base image
1005
backing_fmt Image format of the base image
1006
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1007
-encrypt.format Encrypt the image, format choices: 'aes'
1008
-encrypt.key-secret ID of the secret that provides the AES encryption key
1009
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1010
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1011
+encrypt.cipher-alg Name of encryption cipher algorithm
1012
+encrypt.cipher-mode Name of encryption cipher mode
1013
+encrypt.ivgen-alg Name of IV generator algorithm
1014
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1015
+encrypt.hash-alg Name of encryption hash algorithm
1016
+encrypt.iter-time Time to spend in PBKDF in milliseconds
1017
cluster_size qcow2 cluster size
1018
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1019
lazy_refcounts Postpone refcount updates
1020
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
1021
backing_file File name of a base image
1022
backing_fmt Image format of the base image
1023
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1024
-encrypt.format Encrypt the image, format choices: 'aes'
1025
-encrypt.key-secret ID of the secret that provides the AES encryption key
1026
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1027
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1028
+encrypt.cipher-alg Name of encryption cipher algorithm
1029
+encrypt.cipher-mode Name of encryption cipher mode
1030
+encrypt.ivgen-alg Name of IV generator algorithm
1031
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1032
+encrypt.hash-alg Name of encryption hash algorithm
1033
+encrypt.iter-time Time to spend in PBKDF in milliseconds
1034
cluster_size qcow2 cluster size
1035
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1036
lazy_refcounts Postpone refcount updates
1037
@@ -XXX,XX +XXX,XX @@ compat Compatibility level (0.10 or 1.1)
1038
backing_file File name of a base image
1039
backing_fmt Image format of the base image
1040
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1041
-encrypt.format Encrypt the image, format choices: 'aes'
1042
-encrypt.key-secret ID of the secret that provides the AES encryption key
1043
+encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1044
+encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1045
+encrypt.cipher-alg Name of encryption cipher algorithm
1046
+encrypt.cipher-mode Name of encryption cipher mode
1047
+encrypt.ivgen-alg Name of IV generator algorithm
1048
+encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1049
+encrypt.hash-alg Name of encryption hash algorithm
1050
+encrypt.iter-time Time to spend in PBKDF in milliseconds
1051
cluster_size qcow2 cluster size
1052
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1053
lazy_refcounts Postpone refcount updates
1054
--
160
--
1055
1.8.3.1
161
2.37.3
1056
1057
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Convert another internal
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
function (no semantic change).
5
functions where this holds.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Message-Id: <20220922084924.201610-16-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block/mirror.c | 20 +++++++++++---------
14
block/copy-before-write.c | 9 +++++----
14
1 file changed, 11 insertions(+), 9 deletions(-)
15
1 file changed, 5 insertions(+), 4 deletions(-)
15
16
16
diff --git a/block/mirror.c b/block/mirror.c
17
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block/mirror.c
19
--- a/block/copy-before-write.c
19
+++ b/block/mirror.c
20
+++ b/block/copy-before-write.c
20
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
22
* It's guaranteed that guest writes will not interact in the region until
23
* cbw_snapshot_read_unlock() called.
24
*/
25
-static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs,
26
- int64_t offset, int64_t bytes,
27
- int64_t *pnum, BdrvChild **file)
28
+static coroutine_fn BlockReq *
29
+cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
30
+ int64_t *pnum, BdrvChild **file)
31
{
32
BDRVCopyBeforeWriteState *s = bs->opaque;
33
BlockReq *req = g_new(BlockReq, 1);
34
@@ -XXX,XX +XXX,XX @@ static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs,
35
return req;
21
}
36
}
22
37
23
static void mirror_do_zero_or_discard(MirrorBlockJob *s,
38
-static void cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
24
- int64_t sector_num,
39
+static coroutine_fn void
25
- int nb_sectors,
40
+cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req)
26
+ int64_t offset,
27
+ uint64_t bytes,
28
bool is_discard)
29
{
41
{
30
MirrorOp *op;
42
BDRVCopyBeforeWriteState *s = bs->opaque;
31
@@ -XXX,XX +XXX,XX @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
32
* so the freeing in mirror_iteration_done is nop. */
33
op = g_new0(MirrorOp, 1);
34
op->s = s;
35
- op->offset = sector_num * BDRV_SECTOR_SIZE;
36
- op->bytes = nb_sectors * BDRV_SECTOR_SIZE;
37
+ op->offset = offset;
38
+ op->bytes = bytes;
39
40
s->in_flight++;
41
- s->bytes_in_flight += nb_sectors * BDRV_SECTOR_SIZE;
42
+ s->bytes_in_flight += bytes;
43
if (is_discard) {
44
- blk_aio_pdiscard(s->target, sector_num << BDRV_SECTOR_BITS,
45
+ blk_aio_pdiscard(s->target, offset,
46
op->bytes, mirror_write_complete, op);
47
} else {
48
- blk_aio_pwrite_zeroes(s->target, sector_num * BDRV_SECTOR_SIZE,
49
+ blk_aio_pwrite_zeroes(s->target, offset,
50
op->bytes, s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
51
mirror_write_complete, op);
52
}
53
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
54
break;
55
case MIRROR_METHOD_ZERO:
56
case MIRROR_METHOD_DISCARD:
57
- mirror_do_zero_or_discard(s, sector_num, io_sectors,
58
+ mirror_do_zero_or_discard(s, sector_num * BDRV_SECTOR_SIZE,
59
+ io_sectors * BDRV_SECTOR_SIZE,
60
mirror_method == MIRROR_METHOD_DISCARD);
61
if (write_zeroes_ok) {
62
io_bytes_acct = 0;
63
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
64
continue;
65
}
66
67
- mirror_do_zero_or_discard(s, sector_num, nb_sectors, false);
68
+ mirror_do_zero_or_discard(s, sector_num * BDRV_SECTOR_SIZE,
69
+ nb_sectors * BDRV_SECTOR_SIZE, false);
70
sector_num += nb_sectors;
71
}
72
43
73
--
44
--
74
1.8.3.1
45
2.37.3
75
76
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
easier to reason about than sector-based. Change the internal
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
loop iteration of mirroring to track by bytes instead of sectors
5
functions where this holds.
6
(although we are still guaranteed that we iterate by steps that
7
are both sector-aligned and multiples of the granularity). Drop
8
the now-unused mirror_clip_sectors().
9
6
10
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
9
Message-Id: <20220922084924.201610-17-pbonzini@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
12
---
16
block/mirror.c | 105 +++++++++++++++++++++++++--------------------------------
13
block/curl.c | 2 +-
17
1 file changed, 46 insertions(+), 59 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
18
15
19
diff --git a/block/mirror.c b/block/mirror.c
16
diff --git a/block/curl.c b/block/curl.c
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/block/mirror.c
18
--- a/block/curl.c
22
+++ b/block/mirror.c
19
+++ b/block/curl.c
23
@@ -XXX,XX +XXX,XX @@ static inline int64_t mirror_clip_bytes(MirrorBlockJob *s,
20
@@ -XXX,XX +XXX,XX @@ out_noclean:
24
return MIN(bytes, s->bdev_length - offset);
21
return -EINVAL;
25
}
22
}
26
23
27
-/* Clip nb_sectors relative to sector_num to not exceed end-of-file */
24
-static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
28
-static inline int mirror_clip_sectors(MirrorBlockJob *s,
25
+static void coroutine_fn curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb)
29
- int64_t sector_num,
30
- int nb_sectors)
31
-{
32
- return MIN(nb_sectors,
33
- s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
34
-}
35
-
36
/* Round offset and/or bytes to target cluster if COW is needed, and
37
* return the offset of the adjusted tail against original. */
38
static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
39
@@ -XXX,XX +XXX,XX @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
40
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
41
{
26
{
42
BlockDriverState *source = s->source;
27
CURLState *state;
43
- int64_t sector_num, first_chunk;
28
int running;
44
+ int64_t offset, first_chunk;
45
uint64_t delay_ns = 0;
46
/* At least the first dirty chunk is mirrored in one iteration. */
47
int nb_chunks = 1;
48
- int64_t end = s->bdev_length / BDRV_SECTOR_SIZE;
49
int sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
50
bool write_zeroes_ok = bdrv_can_write_zeroes_with_unmap(blk_bs(s->target));
51
int max_io_bytes = MAX(s->buf_size / MAX_IN_FLIGHT, MAX_IO_BYTES);
52
53
bdrv_dirty_bitmap_lock(s->dirty_bitmap);
54
- sector_num = bdrv_dirty_iter_next(s->dbi);
55
- if (sector_num < 0) {
56
+ offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
57
+ if (offset < 0) {
58
bdrv_set_dirty_iter(s->dbi, 0);
59
- sector_num = bdrv_dirty_iter_next(s->dbi);
60
+ offset = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
61
trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap) *
62
BDRV_SECTOR_SIZE);
63
- assert(sector_num >= 0);
64
+ assert(offset >= 0);
65
}
66
bdrv_dirty_bitmap_unlock(s->dirty_bitmap);
67
68
- first_chunk = sector_num / sectors_per_chunk;
69
+ first_chunk = offset / s->granularity;
70
while (test_bit(first_chunk, s->in_flight_bitmap)) {
71
- trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
72
- s->in_flight);
73
+ trace_mirror_yield_in_flight(s, offset, s->in_flight);
74
mirror_wait_for_io(s);
75
}
76
77
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
78
/* Find the number of consective dirty chunks following the first dirty
79
* one, and wait for in flight requests in them. */
80
bdrv_dirty_bitmap_lock(s->dirty_bitmap);
81
- while (nb_chunks * sectors_per_chunk < (s->buf_size >> BDRV_SECTOR_BITS)) {
82
+ while (nb_chunks * s->granularity < s->buf_size) {
83
int64_t next_dirty;
84
- int64_t next_sector = sector_num + nb_chunks * sectors_per_chunk;
85
- int64_t next_chunk = next_sector / sectors_per_chunk;
86
- if (next_sector >= end ||
87
- !bdrv_get_dirty_locked(source, s->dirty_bitmap, next_sector)) {
88
+ int64_t next_offset = offset + nb_chunks * s->granularity;
89
+ int64_t next_chunk = next_offset / s->granularity;
90
+ if (next_offset >= s->bdev_length ||
91
+ !bdrv_get_dirty_locked(source, s->dirty_bitmap,
92
+ next_offset >> BDRV_SECTOR_BITS)) {
93
break;
94
}
95
if (test_bit(next_chunk, s->in_flight_bitmap)) {
96
break;
97
}
98
99
- next_dirty = bdrv_dirty_iter_next(s->dbi);
100
- if (next_dirty > next_sector || next_dirty < 0) {
101
+ next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
102
+ if (next_dirty > next_offset || next_dirty < 0) {
103
/* The bitmap iterator's cache is stale, refresh it */
104
- bdrv_set_dirty_iter(s->dbi, next_sector);
105
- next_dirty = bdrv_dirty_iter_next(s->dbi);
106
+ bdrv_set_dirty_iter(s->dbi, next_offset >> BDRV_SECTOR_BITS);
107
+ next_dirty = bdrv_dirty_iter_next(s->dbi) * BDRV_SECTOR_SIZE;
108
}
109
- assert(next_dirty == next_sector);
110
+ assert(next_dirty == next_offset);
111
nb_chunks++;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
115
* calling bdrv_get_block_status_above could yield - if some blocks are
116
* marked dirty in this window, we need to know.
117
*/
118
- bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, sector_num,
119
- nb_chunks * sectors_per_chunk);
120
+ bdrv_reset_dirty_bitmap_locked(s->dirty_bitmap, offset >> BDRV_SECTOR_BITS,
121
+ nb_chunks * sectors_per_chunk);
122
bdrv_dirty_bitmap_unlock(s->dirty_bitmap);
123
124
- bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chunks);
125
- while (nb_chunks > 0 && sector_num < end) {
126
+ bitmap_set(s->in_flight_bitmap, offset / s->granularity, nb_chunks);
127
+ while (nb_chunks > 0 && offset < s->bdev_length) {
128
int64_t ret;
129
int io_sectors;
130
+ unsigned int io_bytes;
131
int64_t io_bytes_acct;
132
BlockDriverState *file;
133
enum MirrorMethod {
134
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
135
MIRROR_METHOD_DISCARD
136
} mirror_method = MIRROR_METHOD_COPY;
137
138
- assert(!(sector_num % sectors_per_chunk));
139
- ret = bdrv_get_block_status_above(source, NULL, sector_num,
140
+ assert(!(offset % s->granularity));
141
+ ret = bdrv_get_block_status_above(source, NULL,
142
+ offset >> BDRV_SECTOR_BITS,
143
nb_chunks * sectors_per_chunk,
144
&io_sectors, &file);
145
+ io_bytes = io_sectors * BDRV_SECTOR_SIZE;
146
if (ret < 0) {
147
- io_sectors = MIN(nb_chunks * sectors_per_chunk,
148
- max_io_bytes >> BDRV_SECTOR_BITS);
149
+ io_bytes = MIN(nb_chunks * s->granularity, max_io_bytes);
150
} else if (ret & BDRV_BLOCK_DATA) {
151
- io_sectors = MIN(io_sectors, max_io_bytes >> BDRV_SECTOR_BITS);
152
+ io_bytes = MIN(io_bytes, max_io_bytes);
153
}
154
155
- io_sectors -= io_sectors % sectors_per_chunk;
156
- if (io_sectors < sectors_per_chunk) {
157
- io_sectors = sectors_per_chunk;
158
+ io_bytes -= io_bytes % s->granularity;
159
+ if (io_bytes < s->granularity) {
160
+ io_bytes = s->granularity;
161
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
162
- int64_t target_sector_num;
163
- int target_nb_sectors;
164
- bdrv_round_sectors_to_clusters(blk_bs(s->target), sector_num,
165
- io_sectors, &target_sector_num,
166
- &target_nb_sectors);
167
- if (target_sector_num == sector_num &&
168
- target_nb_sectors == io_sectors) {
169
+ int64_t target_offset;
170
+ unsigned int target_bytes;
171
+ bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
172
+ &target_offset, &target_bytes);
173
+ if (target_offset == offset &&
174
+ target_bytes == io_bytes) {
175
mirror_method = ret & BDRV_BLOCK_ZERO ?
176
MIRROR_METHOD_ZERO :
177
MIRROR_METHOD_DISCARD;
178
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
179
}
180
181
while (s->in_flight >= MAX_IN_FLIGHT) {
182
- trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
183
- s->in_flight);
184
+ trace_mirror_yield_in_flight(s, offset, s->in_flight);
185
mirror_wait_for_io(s);
186
}
187
188
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
189
return 0;
190
}
191
192
- io_sectors = mirror_clip_sectors(s, sector_num, io_sectors);
193
+ io_bytes = mirror_clip_bytes(s, offset, io_bytes);
194
switch (mirror_method) {
195
case MIRROR_METHOD_COPY:
196
- io_bytes_acct = mirror_do_read(s, sector_num * BDRV_SECTOR_SIZE,
197
- io_sectors * BDRV_SECTOR_SIZE);
198
- io_sectors = io_bytes_acct / BDRV_SECTOR_SIZE;
199
+ io_bytes = io_bytes_acct = mirror_do_read(s, offset, io_bytes);
200
break;
201
case MIRROR_METHOD_ZERO:
202
case MIRROR_METHOD_DISCARD:
203
- mirror_do_zero_or_discard(s, sector_num * BDRV_SECTOR_SIZE,
204
- io_sectors * BDRV_SECTOR_SIZE,
205
+ mirror_do_zero_or_discard(s, offset, io_bytes,
206
mirror_method == MIRROR_METHOD_DISCARD);
207
if (write_zeroes_ok) {
208
io_bytes_acct = 0;
209
} else {
210
- io_bytes_acct = io_sectors * BDRV_SECTOR_SIZE;
211
+ io_bytes_acct = io_bytes;
212
}
213
break;
214
default:
215
abort();
216
}
217
- assert(io_sectors);
218
- sector_num += io_sectors;
219
- nb_chunks -= DIV_ROUND_UP(io_sectors, sectors_per_chunk);
220
+ assert(io_bytes);
221
+ offset += io_bytes;
222
+ nb_chunks -= DIV_ROUND_UP(io_bytes, s->granularity);
223
if (s->common.speed) {
224
delay_ns = ratelimit_calculate_delay(&s->limit, io_bytes_acct);
225
}
226
--
29
--
227
1.8.3.1
30
2.37.3
228
229
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Rather than having a void function that modifies its input
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
in-place as the output, change the signature to reduce a layer
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
of indirection and return the result.
5
functions where this holds.
6
6
7
Suggested-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-Id: <20220922084924.201610-18-pbonzini@redhat.com>
10
Reviewed-by: Jeff Cody <jcody@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
block/mirror.c | 15 ++++++++-------
13
block/qed.c | 4 ++--
15
1 file changed, 8 insertions(+), 7 deletions(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
16
15
17
diff --git a/block/mirror.c b/block/mirror.c
16
diff --git a/block/qed.c b/block/qed.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/block/mirror.c
18
--- a/block/qed.c
20
+++ b/block/mirror.c
19
+++ b/block/qed.c
21
@@ -XXX,XX +XXX,XX @@ static void mirror_read_complete(void *opaque, int ret)
20
@@ -XXX,XX +XXX,XX @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
22
aio_context_release(blk_get_aio_context(s->common.blk));
21
return l2_table;
23
}
22
}
24
23
25
-static inline void mirror_clip_sectors(MirrorBlockJob *s,
24
-static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
26
- int64_t sector_num,
25
+static bool coroutine_fn qed_plug_allocating_write_reqs(BDRVQEDState *s)
27
- int *nb_sectors)
28
+static inline int mirror_clip_sectors(MirrorBlockJob *s,
29
+ int64_t sector_num,
30
+ int nb_sectors)
31
{
26
{
32
- *nb_sectors = MIN(*nb_sectors,
27
qemu_co_mutex_lock(&s->table_lock);
33
- s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
28
34
+ return MIN(nb_sectors,
29
@@ -XXX,XX +XXX,XX @@ static bool qed_plug_allocating_write_reqs(BDRVQEDState *s)
35
+ s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
30
return true;
36
}
31
}
37
32
38
/* Round sector_num and/or nb_sectors to target cluster if COW is needed, and
33
-static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
39
@@ -XXX,XX +XXX,XX @@ static int mirror_cow_align(MirrorBlockJob *s,
34
+static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s)
40
}
35
{
41
/* Clipping may result in align_nb_sectors unaligned to chunk boundary, but
36
qemu_co_mutex_lock(&s->table_lock);
42
* that doesn't matter because it's already the end of source image. */
37
assert(s->allocating_write_reqs_plugged);
43
- mirror_clip_sectors(s, align_sector_num, &align_nb_sectors);
44
+ align_nb_sectors = mirror_clip_sectors(s, align_sector_num,
45
+ align_nb_sectors);
46
47
ret = align_sector_num + align_nb_sectors - (*sector_num + *nb_sectors);
48
*sector_num = align_sector_num;
49
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
50
return 0;
51
}
52
53
- mirror_clip_sectors(s, sector_num, &io_sectors);
54
+ io_sectors = mirror_clip_sectors(s, sector_num, io_sectors);
55
switch (mirror_method) {
56
case MIRROR_METHOD_COPY:
57
io_sectors = mirror_do_read(s, sector_num, io_sectors);
58
--
38
--
59
1.8.3.1
39
2.37.3
60
61
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
This was a complete mess. On 2299 indented lines:
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
- 1329 were with spaces only
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
- 617 with tabulations only
5
functions where this holds.
6
- 353 with spaces and tabulations
7
6
8
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20220922084924.201610-19-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
block/vvfat.c | 2054 ++++++++++++++++++++++++++++-----------------------------
14
block/quorum.c | 36 +++++++++++++++++++-----------------
12
1 file changed, 1027 insertions(+), 1027 deletions(-)
15
1 file changed, 19 insertions(+), 17 deletions(-)
13
16
14
diff --git a/block/vvfat.c b/block/vvfat.c
17
diff --git a/block/quorum.c b/block/quorum.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vvfat.c
19
--- a/block/quorum.c
17
+++ b/block/vvfat.c
20
+++ b/block/quorum.c
18
@@ -XXX,XX +XXX,XX @@ static inline void* array_get(array_t* array,unsigned int index) {
21
@@ -XXX,XX +XXX,XX @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b)
19
static inline int array_ensure_allocated(array_t* array, int index)
22
return a->l == b->l;
23
}
24
25
-static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
26
- QEMUIOVector *qiov,
27
- uint64_t offset,
28
- uint64_t bytes,
29
- int flags)
30
+static QuorumAIOCB *coroutine_fn quorum_aio_get(BlockDriverState *bs,
31
+ QEMUIOVector *qiov,
32
+ uint64_t offset, uint64_t bytes,
33
+ int flags)
20
{
34
{
21
if((index + 1) * array->item_size > array->size) {
35
BDRVQuorumState *s = bs->opaque;
22
-    int new_size = (index + 32) * array->item_size;
36
QuorumAIOCB *acb = g_new(QuorumAIOCB, 1);
23
-    array->pointer = g_realloc(array->pointer, new_size);
37
@@ -XXX,XX +XXX,XX @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
24
-    if (!array->pointer)
25
-     return -1;
26
-    array->size = new_size;
27
-    array->next = index + 1;
28
+ int new_size = (index + 32) * array->item_size;
29
+ array->pointer = g_realloc(array->pointer, new_size);
30
+ if (!array->pointer)
31
+ return -1;
32
+ array->size = new_size;
33
+ array->next = index + 1;
34
}
35
36
return 0;
37
@@ -XXX,XX +XXX,XX @@ static inline void* array_get_next(array_t* array) {
38
unsigned int next = array->next;
39
40
if (array_ensure_allocated(array, next) < 0)
41
-    return NULL;
42
+ return NULL;
43
44
array->next = next + 1;
45
return array_get(array, next);
46
@@ -XXX,XX +XXX,XX @@ static inline void* array_get_next(array_t* array) {
47
48
static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {
49
if((array->next+count)*array->item_size>array->size) {
50
-    int increment=count*array->item_size;
51
-    array->pointer=g_realloc(array->pointer,array->size+increment);
52
-    if(!array->pointer)
53
+ int increment=count*array->item_size;
54
+ array->pointer=g_realloc(array->pointer,array->size+increment);
55
+ if(!array->pointer)
56
return NULL;
57
-    array->size+=increment;
58
+ array->size+=increment;
59
}
60
memmove(array->pointer+(index+count)*array->item_size,
61
-        array->pointer+index*array->item_size,
62
-        (array->next-index)*array->item_size);
63
+ array->pointer+index*array->item_size,
64
+ (array->next-index)*array->item_size);
65
array->next+=count;
66
return array->pointer+index*array->item_size;
67
}
68
@@ -XXX,XX +XXX,XX @@ static inline int array_roll(array_t* array,int index_to,int index_from,int coun
69
int is;
70
71
if(!array ||
72
-     index_to<0 || index_to>=array->next ||
73
-     index_from<0 || index_from>=array->next)
74
-    return -1;
75
+ index_to<0 || index_to>=array->next ||
76
+ index_from<0 || index_from>=array->next)
77
+ return -1;
78
79
if(index_to==index_from)
80
-    return 0;
81
+ return 0;
82
83
is=array->item_size;
84
from=array->pointer+index_from*is;
85
@@ -XXX,XX +XXX,XX @@ static inline int array_roll(array_t* array,int index_to,int index_from,int coun
86
memcpy(buf,from,is*count);
87
88
if(index_to<index_from)
89
-    memmove(to+is*count,to,from-to);
90
+ memmove(to+is*count,to,from-to);
91
else
92
-    memmove(from,from+is*count,to-from);
93
+ memmove(from,from+is*count,to-from);
94
95
memcpy(to,buf,is*count);
96
97
@@ -XXX,XX +XXX,XX @@ static inline int array_remove_slice(array_t* array,int index, int count)
98
assert(count > 0);
99
assert(index + count <= array->next);
100
if(array_roll(array,array->next-1,index,count))
101
-    return -1;
102
+ return -1;
103
array->next -= count;
104
return 0;
105
}
106
@@ -XXX,XX +XXX,XX @@ typedef struct bootsector_t {
107
uint32_t total_sectors;
108
union {
109
struct {
110
-     uint8_t drive_number;
111
-     uint8_t current_head;
112
-     uint8_t signature;
113
-     uint32_t id;
114
-     uint8_t volume_label[11];
115
-    } QEMU_PACKED fat16;
116
-    struct {
117
-     uint32_t sectors_per_fat;
118
-     uint16_t flags;
119
-     uint8_t major,minor;
120
-     uint32_t first_cluster_of_root_directory;
121
-     uint16_t info_sector;
122
-     uint16_t backup_boot_sector;
123
-     uint16_t ignored;
124
-    } QEMU_PACKED fat32;
125
+ uint8_t drive_number;
126
+ uint8_t current_head;
127
+ uint8_t signature;
128
+ uint32_t id;
129
+ uint8_t volume_label[11];
130
+ } QEMU_PACKED fat16;
131
+ struct {
132
+ uint32_t sectors_per_fat;
133
+ uint16_t flags;
134
+ uint8_t major,minor;
135
+ uint32_t first_cluster_of_root_directory;
136
+ uint16_t info_sector;
137
+ uint16_t backup_boot_sector;
138
+ uint16_t ignored;
139
+ } QEMU_PACKED fat32;
140
} u;
141
uint8_t fat_type[8];
142
uint8_t ignored[0x1c0];
143
@@ -XXX,XX +XXX,XX @@ typedef struct mapping_t {
144
/* the clusters of a file may be in any order; this points to the first */
145
int first_mapping_index;
146
union {
147
-    /* offset is
148
-     * - the offset in the file (in clusters) for a file, or
149
-     * - the next cluster of the directory for a directory, and
150
-     * - the address of the buffer for a faked entry
151
-     */
152
-    struct {
153
-     uint32_t offset;
154
-    } file;
155
-    struct {
156
-     int parent_mapping_index;
157
-     int first_dir_index;
158
-    } dir;
159
+ /* offset is
160
+ * - the offset in the file (in clusters) for a file, or
161
+ * - the next cluster of the directory for a directory, and
162
+ * - the address of the buffer for a faked entry
163
+ */
164
+ struct {
165
+ uint32_t offset;
166
+ } file;
167
+ struct {
168
+ int parent_mapping_index;
169
+ int first_dir_index;
170
+ } dir;
171
} info;
172
/* path contains the full path, i.e. it always starts with s->path */
173
char* path;
174
175
enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,
176
-    MODE_DIRECTORY = 4, MODE_FAKED = 8,
177
-    MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
178
+ MODE_DIRECTORY = 4, MODE_FAKED = 8,
179
+ MODE_DELETED = 16, MODE_RENAMED = 32 } mode;
180
int read_only;
181
} mapping_t;
182
183
@@ -XXX,XX +XXX,XX @@ static inline int short2long_name(char* dest,const char* src)
184
int len;
185
for(i=0;i<129 && src[i];i++) {
186
dest[2*i]=src[i];
187
-    dest[2*i+1]=0;
188
+ dest[2*i+1]=0;
189
}
190
len=2*i;
191
dest[2*i]=dest[2*i+1]=0;
192
for(i=2*i+2;(i%26);i++)
193
-    dest[i]=0xff;
194
+ dest[i]=0xff;
195
return len;
196
}
197
198
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* fil
199
direntry_t* entry;
200
201
for(i=0;i<number_of_entries;i++) {
202
-    entry=array_get_next(&(s->directory));
203
-    entry->attributes=0xf;
204
-    entry->reserved[0]=0;
205
-    entry->begin=0;
206
-    entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
207
+ entry=array_get_next(&(s->directory));
208
+ entry->attributes=0xf;
209
+ entry->reserved[0]=0;
210
+ entry->begin=0;
211
+ entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
212
}
213
for(i=0;i<26*number_of_entries;i++) {
214
-    int offset=(i%26);
215
-    if(offset<10) offset=1+offset;
216
-    else if(offset<22) offset=14+offset-10;
217
-    else offset=28+offset-22;
218
-    entry=array_get(&(s->directory),s->directory.next-1-(i/26));
219
-    entry->name[offset]=buffer[i];
220
+ int offset=(i%26);
221
+ if(offset<10) offset=1+offset;
222
+ else if(offset<22) offset=14+offset-10;
223
+ else offset=28+offset-22;
224
+ entry=array_get(&(s->directory),s->directory.next-1-(i/26));
225
+ entry->name[offset]=buffer[i];
226
}
227
return array_get(&(s->directory),s->directory.next-number_of_entries);
228
}
229
@@ -XXX,XX +XXX,XX @@ static char is_long_name(const direntry_t* direntry)
230
static char is_short_name(const direntry_t* direntry)
231
{
232
return !is_volume_label(direntry) && !is_long_name(direntry)
233
-    && !is_free(direntry);
234
+ && !is_free(direntry);
235
}
236
237
static char is_directory(const direntry_t* direntry)
238
@@ -XXX,XX +XXX,XX @@ static uint16_t fat_datetime(time_t time,int return_time) {
239
t = &t1;
240
localtime_r(&time,t);
241
if(return_time)
242
-    return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
243
+ return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
244
return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
245
}
246
247
static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value)
248
{
249
if(s->fat_type==32) {
250
-    uint32_t* entry=array_get(&(s->fat),cluster);
251
-    *entry=cpu_to_le32(value);
252
+ uint32_t* entry=array_get(&(s->fat),cluster);
253
+ *entry=cpu_to_le32(value);
254
} else if(s->fat_type==16) {
255
-    uint16_t* entry=array_get(&(s->fat),cluster);
256
-    *entry=cpu_to_le16(value&0xffff);
257
+ uint16_t* entry=array_get(&(s->fat),cluster);
258
+ *entry=cpu_to_le16(value&0xffff);
259
} else {
260
-    int offset = (cluster*3/2);
261
-    unsigned char* p = array_get(&(s->fat), offset);
262
+ int offset = (cluster*3/2);
263
+ unsigned char* p = array_get(&(s->fat), offset);
264
switch (cluster&1) {
265
-    case 0:
266
-        p[0] = value&0xff;
267
-        p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
268
-        break;
269
-    case 1:
270
-        p[0] = (p[0]&0xf) | ((value&0xf)<<4);
271
-        p[1] = (value>>4);
272
-        break;
273
-    }
274
+ case 0:
275
+ p[0] = value&0xff;
276
+ p[1] = (p[1]&0xf0) | ((value>>8)&0xf);
277
+ break;
278
+ case 1:
279
+ p[0] = (p[0]&0xf) | ((value&0xf)<<4);
280
+ p[1] = (value>>4);
281
+ break;
282
+ }
283
}
38
}
284
}
39
}
285
40
286
static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster)
41
-static void quorum_rewrite_entry(void *opaque)
42
+static void coroutine_fn quorum_rewrite_entry(void *opaque)
287
{
43
{
288
if(s->fat_type==32) {
44
QuorumCo *co = opaque;
289
-    uint32_t* entry=array_get(&(s->fat),cluster);
45
QuorumAIOCB *acb = co->acb;
290
-    return le32_to_cpu(*entry);
46
@@ -XXX,XX +XXX,XX @@ free_exit:
291
+ uint32_t* entry=array_get(&(s->fat),cluster);
47
quorum_free_vote_list(&acb->votes);
292
+ return le32_to_cpu(*entry);
48
}
293
} else if(s->fat_type==16) {
49
294
-    uint16_t* entry=array_get(&(s->fat),cluster);
50
-static void read_quorum_children_entry(void *opaque)
295
-    return le16_to_cpu(*entry);
51
+static void coroutine_fn read_quorum_children_entry(void *opaque)
296
+ uint16_t* entry=array_get(&(s->fat),cluster);
52
{
297
+ return le16_to_cpu(*entry);
53
QuorumCo *co = opaque;
298
} else {
54
QuorumAIOCB *acb = co->acb;
299
-    const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
55
@@ -XXX,XX +XXX,XX @@ static void read_quorum_children_entry(void *opaque)
300
-    return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
301
+ const uint8_t* x=(uint8_t*)(s->fat.pointer)+cluster*3/2;
302
+ return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;
303
}
56
}
304
}
57
}
305
58
306
static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry)
59
-static int read_quorum_children(QuorumAIOCB *acb)
60
+static int coroutine_fn read_quorum_children(QuorumAIOCB *acb)
307
{
61
{
308
if(fat_entry>s->max_fat_value-8)
62
BDRVQuorumState *s = acb->bs->opaque;
309
-    return -1;
63
int i;
310
+ return -1;
64
@@ -XXX,XX +XXX,XX @@ static int read_quorum_children(QuorumAIOCB *acb)
311
return 0;
65
return acb->vote_ret;
312
}
66
}
313
67
314
static inline void init_fat(BDRVVVFATState* s)
68
-static int read_fifo_child(QuorumAIOCB *acb)
69
+static int coroutine_fn read_fifo_child(QuorumAIOCB *acb)
315
{
70
{
316
if (s->fat_type == 12) {
71
BDRVQuorumState *s = acb->bs->opaque;
317
-    array_init(&(s->fat),1);
72
int n, ret;
318
-    array_ensure_allocated(&(s->fat),
73
@@ -XXX,XX +XXX,XX @@ static int read_fifo_child(QuorumAIOCB *acb)
319
-        s->sectors_per_fat * 0x200 * 3 / 2 - 1);
74
return ret;
320
+ array_init(&(s->fat),1);
321
+ array_ensure_allocated(&(s->fat),
322
+ s->sectors_per_fat * 0x200 * 3 / 2 - 1);
323
} else {
324
-    array_init(&(s->fat),(s->fat_type==32?4:2));
325
-    array_ensure_allocated(&(s->fat),
326
-        s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
327
+ array_init(&(s->fat),(s->fat_type==32?4:2));
328
+ array_ensure_allocated(&(s->fat),
329
+ s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
330
}
331
memset(s->fat.pointer,0,s->fat.size);
332
333
switch(s->fat_type) {
334
-    case 12: s->max_fat_value=0xfff; break;
335
-    case 16: s->max_fat_value=0xffff; break;
336
-    case 32: s->max_fat_value=0x0fffffff; break;
337
-    default: s->max_fat_value=0; /* error... */
338
+ case 12: s->max_fat_value=0xfff; break;
339
+ case 16: s->max_fat_value=0xffff; break;
340
+ case 32: s->max_fat_value=0x0fffffff; break;
341
+ default: s->max_fat_value=0; /* error... */
342
}
343
344
}
75
}
345
@@ -XXX,XX +XXX,XX @@ static inline void init_fat(BDRVVVFATState* s)
76
346
/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
77
-static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
347
/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
78
- QEMUIOVector *qiov, BdrvRequestFlags flags)
348
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
79
+static int coroutine_fn quorum_co_preadv(BlockDriverState *bs,
349
-    unsigned int directory_start, const char* filename, int is_dot)
80
+ int64_t offset, int64_t bytes,
350
+ unsigned int directory_start, const char* filename, int is_dot)
81
+ QEMUIOVector *qiov,
82
+ BdrvRequestFlags flags)
351
{
83
{
352
int i,j,long_index=s->directory.next;
84
BDRVQuorumState *s = bs->opaque;
353
direntry_t* entry = NULL;
85
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
354
direntry_t* entry_long = NULL;
86
@@ -XXX,XX +XXX,XX @@ static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
355
87
return ret;
356
if(is_dot) {
88
}
357
-    entry=array_get_next(&(s->directory));
89
358
+ entry=array_get_next(&(s->directory));
90
-static void write_quorum_entry(void *opaque)
359
memset(entry->name, 0x20, sizeof(entry->name));
91
+static void coroutine_fn write_quorum_entry(void *opaque)
360
-    memcpy(entry->name,filename,strlen(filename));
361
-    return entry;
362
+ memcpy(entry->name,filename,strlen(filename));
363
+ return entry;
364
}
365
366
entry_long=create_long_filename(s,filename);
367
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
368
i = strlen(filename);
369
for(j = i - 1; j>0 && filename[j]!='.';j--);
370
if (j > 0)
371
-    i = (j > 8 ? 8 : j);
372
+ i = (j > 8 ? 8 : j);
373
else if (i > 8)
374
-    i = 8;
375
+ i = 8;
376
377
entry=array_get_next(&(s->directory));
378
memset(entry->name, 0x20, sizeof(entry->name));
379
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
380
381
/* upcase & remove unwanted characters */
382
for(i=10;i>=0;i--) {
383
-    if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
384
-    if(entry->name[i]<=' ' || entry->name[i]>0x7f
385
-        || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
386
-     entry->name[i]='_';
387
+ if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
388
+ if(entry->name[i]<=' ' || entry->name[i]>0x7f
389
+ || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
390
+ entry->name[i]='_';
391
else if(entry->name[i]>='a' && entry->name[i]<='z')
392
entry->name[i]+='A'-'a';
393
}
394
395
/* mangle duplicates */
396
while(1) {
397
-    direntry_t* entry1=array_get(&(s->directory),directory_start);
398
-    int j;
399
-
400
-    for(;entry1<entry;entry1++)
401
-     if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
402
-        break; /* found dupe */
403
-    if(entry1==entry) /* no dupe found */
404
-     break;
405
-
406
-    /* use all 8 characters of name */
407
-    if(entry->name[7]==' ') {
408
-     int j;
409
-     for(j=6;j>0 && entry->name[j]==' ';j--)
410
-        entry->name[j]='~';
411
-    }
412
-
413
-    /* increment number */
414
-    for(j=7;j>0 && entry->name[j]=='9';j--)
415
-     entry->name[j]='0';
416
-    if(j>0) {
417
-     if(entry->name[j]<'0' || entry->name[j]>'9')
418
-     entry->name[j]='0';
419
-     else
420
-     entry->name[j]++;
421
-    }
422
+ direntry_t* entry1=array_get(&(s->directory),directory_start);
423
+ int j;
424
+
425
+ for(;entry1<entry;entry1++)
426
+ if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
427
+ break; /* found dupe */
428
+ if(entry1==entry) /* no dupe found */
429
+ break;
430
+
431
+ /* use all 8 characters of name */
432
+ if(entry->name[7]==' ') {
433
+ int j;
434
+ for(j=6;j>0 && entry->name[j]==' ';j--)
435
+ entry->name[j]='~';
436
+ }
437
+
438
+ /* increment number */
439
+ for(j=7;j>0 && entry->name[j]=='9';j--)
440
+ entry->name[j]='0';
441
+ if(j>0) {
442
+ if(entry->name[j]<'0' || entry->name[j]>'9')
443
+ entry->name[j]='0';
444
+ else
445
+ entry->name[j]++;
446
+ }
447
}
448
449
/* calculate checksum; propagate to long name */
450
if(entry_long) {
451
uint8_t chksum=fat_chksum(entry);
452
453
-    /* calculate anew, because realloc could have taken place */
454
-    entry_long=array_get(&(s->directory),long_index);
455
-    while(entry_long<entry && is_long_name(entry_long)) {
456
-     entry_long->reserved[1]=chksum;
457
-     entry_long++;
458
-    }
459
+ /* calculate anew, because realloc could have taken place */
460
+ entry_long=array_get(&(s->directory),long_index);
461
+ while(entry_long<entry && is_long_name(entry_long)) {
462
+ entry_long->reserved[1]=chksum;
463
+ entry_long++;
464
+ }
465
}
466
467
return entry;
468
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
469
assert(mapping->mode & MODE_DIRECTORY);
470
471
if(!dir) {
472
-    mapping->end = mapping->begin;
473
-    return -1;
474
+ mapping->end = mapping->begin;
475
+ return -1;
476
}
477
478
i = mapping->info.dir.first_dir_index =
479
-     first_cluster == 0 ? 0 : s->directory.next;
480
+ first_cluster == 0 ? 0 : s->directory.next;
481
482
/* actually read the directory, and allocate the mappings */
483
while((entry=readdir(dir))) {
484
-    unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
485
+ unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
486
char* buffer;
487
-    direntry_t* direntry;
488
+ direntry_t* direntry;
489
struct stat st;
490
-    int is_dot=!strcmp(entry->d_name,".");
491
-    int is_dotdot=!strcmp(entry->d_name,"..");
492
+ int is_dot=!strcmp(entry->d_name,".");
493
+ int is_dotdot=!strcmp(entry->d_name,"..");
494
495
-    if(first_cluster == 0 && (is_dotdot || is_dot))
496
-     continue;
497
+ if(first_cluster == 0 && (is_dotdot || is_dot))
498
+ continue;
499
500
-    buffer = g_malloc(length);
501
-    snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
502
+ buffer = g_malloc(length);
503
+ snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
504
505
-    if(stat(buffer,&st)<0) {
506
+ if(stat(buffer,&st)<0) {
507
g_free(buffer);
508
continue;
509
-    }
510
-
511
-    /* create directory entry for this file */
512
-    direntry=create_short_and_long_name(s, i, entry->d_name,
513
-        is_dot || is_dotdot);
514
-    direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
515
-    direntry->reserved[0]=direntry->reserved[1]=0;
516
-    direntry->ctime=fat_datetime(st.st_ctime,1);
517
-    direntry->cdate=fat_datetime(st.st_ctime,0);
518
-    direntry->adate=fat_datetime(st.st_atime,0);
519
-    direntry->begin_hi=0;
520
-    direntry->mtime=fat_datetime(st.st_mtime,1);
521
-    direntry->mdate=fat_datetime(st.st_mtime,0);
522
-    if(is_dotdot)
523
-     set_begin_of_direntry(direntry, first_cluster_of_parent);
524
-    else if(is_dot)
525
-     set_begin_of_direntry(direntry, first_cluster);
526
-    else
527
-     direntry->begin=0; /* do that later */
528
+ }
529
+
530
+ /* create directory entry for this file */
531
+ direntry=create_short_and_long_name(s, i, entry->d_name,
532
+ is_dot || is_dotdot);
533
+ direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
534
+ direntry->reserved[0]=direntry->reserved[1]=0;
535
+ direntry->ctime=fat_datetime(st.st_ctime,1);
536
+ direntry->cdate=fat_datetime(st.st_ctime,0);
537
+ direntry->adate=fat_datetime(st.st_atime,0);
538
+ direntry->begin_hi=0;
539
+ direntry->mtime=fat_datetime(st.st_mtime,1);
540
+ direntry->mdate=fat_datetime(st.st_mtime,0);
541
+ if(is_dotdot)
542
+ set_begin_of_direntry(direntry, first_cluster_of_parent);
543
+ else if(is_dot)
544
+ set_begin_of_direntry(direntry, first_cluster);
545
+ else
546
+ direntry->begin=0; /* do that later */
547
if (st.st_size > 0x7fffffff) {
548
-     fprintf(stderr, "File %s is larger than 2GB\n", buffer);
549
+ fprintf(stderr, "File %s is larger than 2GB\n", buffer);
550
g_free(buffer);
551
closedir(dir);
552
-     return -2;
553
+ return -2;
554
}
555
-    direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
556
-
557
-    /* create mapping for this file */
558
-    if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
559
-     s->current_mapping = array_get_next(&(s->mapping));
560
-     s->current_mapping->begin=0;
561
-     s->current_mapping->end=st.st_size;
562
-     /*
563
-     * we get the direntry of the most recent direntry, which
564
-     * contains the short name and all the relevant information.
565
-     */
566
-     s->current_mapping->dir_index=s->directory.next-1;
567
-     s->current_mapping->first_mapping_index = -1;
568
-     if (S_ISDIR(st.st_mode)) {
569
-        s->current_mapping->mode = MODE_DIRECTORY;
570
-        s->current_mapping->info.dir.parent_mapping_index =
571
-         mapping_index;
572
-     } else {
573
-        s->current_mapping->mode = MODE_UNDEFINED;
574
-        s->current_mapping->info.file.offset = 0;
575
-     }
576
-     s->current_mapping->path=buffer;
577
-     s->current_mapping->read_only =
578
-        (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
579
+ direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
580
+
581
+ /* create mapping for this file */
582
+ if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {
583
+ s->current_mapping = array_get_next(&(s->mapping));
584
+ s->current_mapping->begin=0;
585
+ s->current_mapping->end=st.st_size;
586
+ /*
587
+ * we get the direntry of the most recent direntry, which
588
+ * contains the short name and all the relevant information.
589
+ */
590
+ s->current_mapping->dir_index=s->directory.next-1;
591
+ s->current_mapping->first_mapping_index = -1;
592
+ if (S_ISDIR(st.st_mode)) {
593
+ s->current_mapping->mode = MODE_DIRECTORY;
594
+ s->current_mapping->info.dir.parent_mapping_index =
595
+ mapping_index;
596
+ } else {
597
+ s->current_mapping->mode = MODE_UNDEFINED;
598
+ s->current_mapping->info.file.offset = 0;
599
+ }
600
+ s->current_mapping->path=buffer;
601
+ s->current_mapping->read_only =
602
+ (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;
603
} else {
604
g_free(buffer);
605
}
606
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
607
608
/* fill with zeroes up to the end of the cluster */
609
while(s->directory.next%(0x10*s->sectors_per_cluster)) {
610
-    direntry_t* direntry=array_get_next(&(s->directory));
611
-    memset(direntry,0,sizeof(direntry_t));
612
+ direntry_t* direntry=array_get_next(&(s->directory));
613
+ memset(direntry,0,sizeof(direntry_t));
614
}
615
616
/* TODO: if there are more entries, bootsector has to be adjusted! */
617
#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
618
if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
619
-    /* root directory */
620
-    int cur = s->directory.next;
621
-    array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
622
-    s->directory.next = ROOT_ENTRIES;
623
-    memset(array_get(&(s->directory), cur), 0,
624
-        (ROOT_ENTRIES - cur) * sizeof(direntry_t));
625
+ /* root directory */
626
+ int cur = s->directory.next;
627
+ array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
628
+ s->directory.next = ROOT_ENTRIES;
629
+ memset(array_get(&(s->directory), cur), 0,
630
+ (ROOT_ENTRIES - cur) * sizeof(direntry_t));
631
}
632
633
/* reget the mapping, since s->mapping was possibly realloc()ed */
634
mapping = array_get(&(s->mapping), mapping_index);
635
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
636
-    * 0x20 / s->cluster_size;
637
+ * 0x20 / s->cluster_size;
638
mapping->end = first_cluster;
639
640
direntry = array_get(&(s->directory), mapping->dir_index);
641
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
642
643
/* add volume label */
644
{
645
-    direntry_t* entry=array_get_next(&(s->directory));
646
-    entry->attributes=0x28; /* archive | volume label */
647
+ direntry_t* entry=array_get_next(&(s->directory));
648
+ entry->attributes=0x28; /* archive | volume label */
649
memcpy(entry->name, s->volume_label, sizeof(entry->name));
650
}
651
652
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
653
mapping->path = g_strdup(dirname);
654
i = strlen(mapping->path);
655
if (i > 0 && mapping->path[i - 1] == '/')
656
-    mapping->path[i - 1] = '\0';
657
+ mapping->path[i - 1] = '\0';
658
mapping->mode = MODE_DIRECTORY;
659
mapping->read_only = 0;
660
s->path = mapping->path;
661
662
for (i = 0, cluster = 0; i < s->mapping.next; i++) {
663
-    /* MS-DOS expects the FAT to be 0 for the root directory
664
-     * (except for the media byte). */
665
-    /* LATER TODO: still true for FAT32? */
666
-    int fix_fat = (i != 0);
667
-    mapping = array_get(&(s->mapping), i);
668
+ /* MS-DOS expects the FAT to be 0 for the root directory
669
+ * (except for the media byte). */
670
+ /* LATER TODO: still true for FAT32? */
671
+ int fix_fat = (i != 0);
672
+ mapping = array_get(&(s->mapping), i);
673
674
if (mapping->mode & MODE_DIRECTORY) {
675
-     mapping->begin = cluster;
676
-     if(read_directory(s, i)) {
677
+ mapping->begin = cluster;
678
+ if(read_directory(s, i)) {
679
error_setg(errp, "Could not read directory %s",
680
mapping->path);
681
-        return -1;
682
-     }
683
-     mapping = array_get(&(s->mapping), i);
684
-    } else {
685
-     assert(mapping->mode == MODE_UNDEFINED);
686
-     mapping->mode=MODE_NORMAL;
687
-     mapping->begin = cluster;
688
-     if (mapping->end > 0) {
689
-        direntry_t* direntry = array_get(&(s->directory),
690
-            mapping->dir_index);
691
-
692
-        mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
693
-        set_begin_of_direntry(direntry, mapping->begin);
694
-     } else {
695
-        mapping->end = cluster + 1;
696
-        fix_fat = 0;
697
-     }
698
-    }
699
-
700
-    assert(mapping->begin < mapping->end);
701
-
702
-    /* next free cluster */
703
-    cluster = mapping->end;
704
-
705
-    if(cluster > s->cluster_count) {
706
+ return -1;
707
+ }
708
+ mapping = array_get(&(s->mapping), i);
709
+ } else {
710
+ assert(mapping->mode == MODE_UNDEFINED);
711
+ mapping->mode=MODE_NORMAL;
712
+ mapping->begin = cluster;
713
+ if (mapping->end > 0) {
714
+ direntry_t* direntry = array_get(&(s->directory),
715
+ mapping->dir_index);
716
+
717
+ mapping->end = cluster + 1 + (mapping->end-1)/s->cluster_size;
718
+ set_begin_of_direntry(direntry, mapping->begin);
719
+ } else {
720
+ mapping->end = cluster + 1;
721
+ fix_fat = 0;
722
+ }
723
+ }
724
+
725
+ assert(mapping->begin < mapping->end);
726
+
727
+ /* next free cluster */
728
+ cluster = mapping->end;
729
+
730
+ if(cluster > s->cluster_count) {
731
error_setg(errp,
732
"Directory does not fit in FAT%d (capacity %.2f MB)",
733
s->fat_type, s->sector_count / 2000.0);
734
return -1;
735
-    }
736
+ }
737
738
-    /* fix fat for entry */
739
-    if (fix_fat) {
740
-     int j;
741
-     for(j = mapping->begin; j < mapping->end - 1; j++)
742
-        fat_set(s, j, j+1);
743
-     fat_set(s, mapping->end - 1, s->max_fat_value);
744
-    }
745
+ /* fix fat for entry */
746
+ if (fix_fat) {
747
+ int j;
748
+ for(j = mapping->begin; j < mapping->end - 1; j++)
749
+ fat_set(s, j, j+1);
750
+ fat_set(s, mapping->end - 1, s->max_fat_value);
751
+ }
752
}
753
754
mapping = array_get(&(s->mapping), 0);
755
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
756
757
switch (s->fat_type) {
758
case 32:
759
-     fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
760
+ fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
761
"You are welcome to do so!\n");
762
break;
763
case 16:
764
@@ -XXX,XX +XXX,XX @@ static void vvfat_refresh_limits(BlockDriverState *bs, Error **errp)
765
static inline void vvfat_close_current_file(BDRVVVFATState *s)
766
{
92
{
767
if(s->current_mapping) {
93
QuorumCo *co = opaque;
768
-    s->current_mapping = NULL;
94
QuorumAIOCB *acb = co->acb;
769
-    if (s->current_fd) {
95
@@ -XXX,XX +XXX,XX @@ static void write_quorum_entry(void *opaque)
770
-        qemu_close(s->current_fd);
771
-        s->current_fd = 0;
772
-    }
773
+ s->current_mapping = NULL;
774
+ if (s->current_fd) {
775
+ qemu_close(s->current_fd);
776
+ s->current_fd = 0;
777
+ }
778
}
779
s->current_cluster = -1;
780
}
781
@@ -XXX,XX +XXX,XX @@ static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num
782
{
783
while(1) {
784
int index3;
785
-    mapping_t* mapping;
786
-    index3=(index1+index2)/2;
787
-    mapping=array_get(&(s->mapping),index3);
788
-    assert(mapping->begin < mapping->end);
789
-    if(mapping->begin>=cluster_num) {
790
-     assert(index2!=index3 || index2==0);
791
-     if(index2==index3)
792
-        return index1;
793
-     index2=index3;
794
-    } else {
795
-     if(index1==index3)
796
-        return mapping->end<=cluster_num ? index2 : index1;
797
-     index1=index3;
798
-    }
799
-    assert(index1<=index2);
800
-    DLOG(mapping=array_get(&(s->mapping),index1);
801
-    assert(mapping->begin<=cluster_num);
802
-    assert(index2 >= s->mapping.next ||
803
-        ((mapping = array_get(&(s->mapping),index2)) &&
804
-        mapping->end>cluster_num)));
805
+ mapping_t* mapping;
806
+ index3=(index1+index2)/2;
807
+ mapping=array_get(&(s->mapping),index3);
808
+ assert(mapping->begin < mapping->end);
809
+ if(mapping->begin>=cluster_num) {
810
+ assert(index2!=index3 || index2==0);
811
+ if(index2==index3)
812
+ return index1;
813
+ index2=index3;
814
+ } else {
815
+ if(index1==index3)
816
+ return mapping->end<=cluster_num ? index2 : index1;
817
+ index1=index3;
818
+ }
819
+ assert(index1<=index2);
820
+ DLOG(mapping=array_get(&(s->mapping),index1);
821
+ assert(mapping->begin<=cluster_num);
822
+ assert(index2 >= s->mapping.next ||
823
+ ((mapping = array_get(&(s->mapping),index2)) &&
824
+ mapping->end>cluster_num)));
825
}
96
}
826
}
97
}
827
98
828
@@ -XXX,XX +XXX,XX @@ static inline mapping_t* find_mapping_for_cluster(BDRVVVFATState* s,int cluster_
99
-static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
829
static int open_file(BDRVVVFATState* s,mapping_t* mapping)
100
- int64_t bytes, QEMUIOVector *qiov,
101
- BdrvRequestFlags flags)
102
+static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
103
+ int64_t bytes, QEMUIOVector *qiov,
104
+ BdrvRequestFlags flags)
830
{
105
{
831
if(!mapping)
106
BDRVQuorumState *s = bs->opaque;
832
-    return -1;
107
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
833
+ return -1;
108
@@ -XXX,XX +XXX,XX @@ static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset,
834
if(!s->current_mapping ||
109
return ret;
835
-     strcmp(s->current_mapping->path,mapping->path)) {
836
-    /* open file */
837
-    int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
838
-    if(fd<0)
839
-     return -1;
840
-    vvfat_close_current_file(s);
841
-    s->current_fd = fd;
842
-    s->current_mapping = mapping;
843
+ strcmp(s->current_mapping->path,mapping->path)) {
844
+ /* open file */
845
+ int fd = qemu_open(mapping->path, O_RDONLY | O_BINARY | O_LARGEFILE);
846
+ if(fd<0)
847
+ return -1;
848
+ vvfat_close_current_file(s);
849
+ s->current_fd = fd;
850
+ s->current_mapping = mapping;
851
}
852
return 0;
853
}
110
}
854
@@ -XXX,XX +XXX,XX @@ static int open_file(BDRVVVFATState* s,mapping_t* mapping)
111
855
static inline int read_cluster(BDRVVVFATState *s,int cluster_num)
112
-static int quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
113
- int64_t bytes, BdrvRequestFlags flags)
114
+static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs,
115
+ int64_t offset, int64_t bytes,
116
+ BdrvRequestFlags flags)
117
856
{
118
{
857
if(s->current_cluster != cluster_num) {
119
return quorum_co_pwritev(bs, offset, bytes, NULL,
858
-    int result=0;
859
-    off_t offset;
860
-    assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
861
-    if(!s->current_mapping
862
-        || s->current_mapping->begin>cluster_num
863
-        || s->current_mapping->end<=cluster_num) {
864
-     /* binary search of mappings for file */
865
-     mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
866
-
867
-     assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
868
-
869
-     if (mapping && mapping->mode & MODE_DIRECTORY) {
870
-        vvfat_close_current_file(s);
871
-        s->current_mapping = mapping;
872
+ int result=0;
873
+ off_t offset;
874
+ assert(!s->current_mapping || s->current_fd || (s->current_mapping->mode & MODE_DIRECTORY));
875
+ if(!s->current_mapping
876
+ || s->current_mapping->begin>cluster_num
877
+ || s->current_mapping->end<=cluster_num) {
878
+ /* binary search of mappings for file */
879
+ mapping_t* mapping=find_mapping_for_cluster(s,cluster_num);
880
+
881
+ assert(!mapping || (cluster_num>=mapping->begin && cluster_num<mapping->end));
882
+
883
+ if (mapping && mapping->mode & MODE_DIRECTORY) {
884
+ vvfat_close_current_file(s);
885
+ s->current_mapping = mapping;
886
read_cluster_directory:
887
-        offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
888
-        s->cluster = (unsigned char*)s->directory.pointer+offset
889
-            + 0x20*s->current_mapping->info.dir.first_dir_index;
890
-        assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
891
-        assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
892
-        s->current_cluster = cluster_num;
893
-        return 0;
894
-     }
895
-
896
-     if(open_file(s,mapping))
897
-        return -2;
898
-    } else if (s->current_mapping->mode & MODE_DIRECTORY)
899
-     goto read_cluster_directory;
900
-
901
-    assert(s->current_fd);
902
-
903
-    offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
904
-    if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
905
-     return -3;
906
-    s->cluster=s->cluster_buffer;
907
-    result=read(s->current_fd,s->cluster,s->cluster_size);
908
-    if(result<0) {
909
-     s->current_cluster = -1;
910
-     return -1;
911
-    }
912
-    s->current_cluster = cluster_num;
913
+ offset = s->cluster_size*(cluster_num-s->current_mapping->begin);
914
+ s->cluster = (unsigned char*)s->directory.pointer+offset
915
+ + 0x20*s->current_mapping->info.dir.first_dir_index;
916
+ assert(((s->cluster-(unsigned char*)s->directory.pointer)%s->cluster_size)==0);
917
+ assert((char*)s->cluster+s->cluster_size <= s->directory.pointer+s->directory.next*s->directory.item_size);
918
+ s->current_cluster = cluster_num;
919
+ return 0;
920
+ }
921
+
922
+ if(open_file(s,mapping))
923
+ return -2;
924
+ } else if (s->current_mapping->mode & MODE_DIRECTORY)
925
+ goto read_cluster_directory;
926
+
927
+ assert(s->current_fd);
928
+
929
+ offset=s->cluster_size*(cluster_num-s->current_mapping->begin)+s->current_mapping->info.file.offset;
930
+ if(lseek(s->current_fd, offset, SEEK_SET)!=offset)
931
+ return -3;
932
+ s->cluster=s->cluster_buffer;
933
+ result=read(s->current_fd,s->cluster,s->cluster_size);
934
+ if(result<0) {
935
+ s->current_cluster = -1;
936
+ return -1;
937
+ }
938
+ s->current_cluster = cluster_num;
939
}
940
return 0;
941
}
942
@@ -XXX,XX +XXX,XX @@ static void print_direntry(const direntry_t* direntry)
943
944
fprintf(stderr, "direntry %p: ", direntry);
945
if(!direntry)
946
-    return;
947
+ return;
948
if(is_long_name(direntry)) {
949
-    unsigned char* c=(unsigned char*)direntry;
950
-    int i;
951
-    for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
952
+ unsigned char* c=(unsigned char*)direntry;
953
+ int i;
954
+ for(i=1;i<11 && c[i] && c[i]!=0xff;i+=2)
955
#define ADD_CHAR(c) {buffer[j] = (c); if (buffer[j] < ' ') buffer[j] = 0xb0; j++;}
956
-     ADD_CHAR(c[i]);
957
-    for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
958
-     ADD_CHAR(c[i]);
959
-    for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
960
-     ADD_CHAR(c[i]);
961
-    buffer[j] = 0;
962
-    fprintf(stderr, "%s\n", buffer);
963
+ ADD_CHAR(c[i]);
964
+ for(i=14;i<26 && c[i] && c[i]!=0xff;i+=2)
965
+ ADD_CHAR(c[i]);
966
+ for(i=28;i<32 && c[i] && c[i]!=0xff;i+=2)
967
+ ADD_CHAR(c[i]);
968
+ buffer[j] = 0;
969
+ fprintf(stderr, "%s\n", buffer);
970
} else {
971
-    int i;
972
-    for(i=0;i<11;i++)
973
-     ADD_CHAR(direntry->name[i]);
974
-    buffer[j] = 0;
975
-    fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
976
-        buffer,
977
-        direntry->attributes,
978
-        begin_of_direntry(direntry),le32_to_cpu(direntry->size));
979
+ int i;
980
+ for(i=0;i<11;i++)
981
+ ADD_CHAR(direntry->name[i]);
982
+ buffer[j] = 0;
983
+ fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
984
+ buffer,
985
+ direntry->attributes,
986
+ begin_of_direntry(direntry),le32_to_cpu(direntry->size));
987
}
988
}
989
990
@@ -XXX,XX +XXX,XX @@ static void print_mapping(const mapping_t* mapping)
991
mapping->first_mapping_index, mapping->path, mapping->mode);
992
993
if (mapping->mode & MODE_DIRECTORY)
994
-    fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
995
+ fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
996
else
997
-    fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
998
+ fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
999
}
1000
#endif
1001
1002
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1003
int i;
1004
1005
for(i=0;i<nb_sectors;i++,sector_num++) {
1006
-    if (sector_num >= bs->total_sectors)
1007
-     return -1;
1008
-    if (s->qcow) {
1009
-     int n;
1010
+ if (sector_num >= bs->total_sectors)
1011
+ return -1;
1012
+ if (s->qcow) {
1013
+ int n;
1014
int ret;
1015
ret = bdrv_is_allocated(s->qcow->bs, sector_num,
1016
nb_sectors - i, &n);
1017
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1018
continue;
1019
}
1020
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
1021
-    }
1022
-    if(sector_num<s->faked_sectors) {
1023
-     if(sector_num<s->first_sectors_number)
1024
-        memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1025
-     else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1026
-        memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1027
-     else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1028
-        memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1029
-    } else {
1030
-     uint32_t sector=sector_num-s->faked_sectors,
1031
-     sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1032
-     cluster_num=sector/s->sectors_per_cluster;
1033
-     if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1034
-        /* LATER TODO: strict: return -1; */
1035
-        memset(buf+i*0x200,0,0x200);
1036
-        continue;
1037
-     }
1038
-     memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1039
-    }
1040
+ }
1041
+ if(sector_num<s->faked_sectors) {
1042
+ if(sector_num<s->first_sectors_number)
1043
+ memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
1044
+ else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
1045
+ memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
1046
+ else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
1047
+ memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
1048
+ } else {
1049
+ uint32_t sector=sector_num-s->faked_sectors,
1050
+ sector_offset_in_cluster=(sector%s->sectors_per_cluster),
1051
+ cluster_num=sector/s->sectors_per_cluster;
1052
+ if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
1053
+ /* LATER TODO: strict: return -1; */
1054
+ memset(buf+i*0x200,0,0x200);
1055
+ continue;
1056
+ }
1057
+ memcpy(buf+i*0x200,s->cluster+sector_offset_in_cluster*0x200,0x200);
1058
+ }
1059
}
1060
return 0;
1061
}
1062
@@ -XXX,XX +XXX,XX @@ vvfat_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
1063
typedef struct commit_t {
1064
char* path;
1065
union {
1066
-    struct { uint32_t cluster; } rename;
1067
-    struct { int dir_index; uint32_t modified_offset; } writeout;
1068
-    struct { uint32_t first_cluster; } new_file;
1069
-    struct { uint32_t cluster; } mkdir;
1070
+ struct { uint32_t cluster; } rename;
1071
+ struct { int dir_index; uint32_t modified_offset; } writeout;
1072
+ struct { uint32_t first_cluster; } new_file;
1073
+ struct { uint32_t cluster; } mkdir;
1074
} param;
1075
/* DELETEs and RMDIRs are handled differently: see handle_deletes() */
1076
enum {
1077
-    ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1078
+ ACTION_RENAME, ACTION_WRITEOUT, ACTION_NEW_FILE, ACTION_MKDIR
1079
} action;
1080
} commit_t;
1081
1082
@@ -XXX,XX +XXX,XX @@ static void clear_commits(BDRVVVFATState* s)
1083
int i;
1084
DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
1085
for (i = 0; i < s->commits.next; i++) {
1086
-    commit_t* commit = array_get(&(s->commits), i);
1087
-    assert(commit->path || commit->action == ACTION_WRITEOUT);
1088
-    if (commit->action != ACTION_WRITEOUT) {
1089
-     assert(commit->path);
1090
+ commit_t* commit = array_get(&(s->commits), i);
1091
+ assert(commit->path || commit->action == ACTION_WRITEOUT);
1092
+ if (commit->action != ACTION_WRITEOUT) {
1093
+ assert(commit->path);
1094
g_free(commit->path);
1095
-    } else
1096
-     assert(commit->path == NULL);
1097
+ } else
1098
+ assert(commit->path == NULL);
1099
}
1100
s->commits.next = 0;
1101
}
1102
1103
static void schedule_rename(BDRVVVFATState* s,
1104
-    uint32_t cluster, char* new_path)
1105
+ uint32_t cluster, char* new_path)
1106
{
1107
commit_t* commit = array_get_next(&(s->commits));
1108
commit->path = new_path;
1109
@@ -XXX,XX +XXX,XX @@ static void schedule_rename(BDRVVVFATState* s,
1110
}
1111
1112
static void schedule_writeout(BDRVVVFATState* s,
1113
-    int dir_index, uint32_t modified_offset)
1114
+ int dir_index, uint32_t modified_offset)
1115
{
1116
commit_t* commit = array_get_next(&(s->commits));
1117
commit->path = NULL;
1118
@@ -XXX,XX +XXX,XX @@ static void schedule_writeout(BDRVVVFATState* s,
1119
}
1120
1121
static void schedule_new_file(BDRVVVFATState* s,
1122
-    char* path, uint32_t first_cluster)
1123
+ char* path, uint32_t first_cluster)
1124
{
1125
commit_t* commit = array_get_next(&(s->commits));
1126
commit->path = path;
1127
@@ -XXX,XX +XXX,XX @@ static void lfn_init(long_file_name* lfn)
1128
1129
/* return 0 if parsed successfully, > 0 if no long name, < 0 if error */
1130
static int parse_long_name(long_file_name* lfn,
1131
-    const direntry_t* direntry)
1132
+ const direntry_t* direntry)
1133
{
1134
int i, j, offset;
1135
const unsigned char* pointer = (const unsigned char*)direntry;
1136
1137
if (!is_long_name(direntry))
1138
-    return 1;
1139
+ return 1;
1140
1141
if (pointer[0] & 0x40) {
1142
-    lfn->sequence_number = pointer[0] & 0x3f;
1143
-    lfn->checksum = pointer[13];
1144
-    lfn->name[0] = 0;
1145
-    lfn->name[lfn->sequence_number * 13] = 0;
1146
+ lfn->sequence_number = pointer[0] & 0x3f;
1147
+ lfn->checksum = pointer[13];
1148
+ lfn->name[0] = 0;
1149
+ lfn->name[lfn->sequence_number * 13] = 0;
1150
} else if ((pointer[0] & 0x3f) != --lfn->sequence_number)
1151
-    return -1;
1152
+ return -1;
1153
else if (pointer[13] != lfn->checksum)
1154
-    return -2;
1155
+ return -2;
1156
else if (pointer[12] || pointer[26] || pointer[27])
1157
-    return -3;
1158
+ return -3;
1159
1160
offset = 13 * (lfn->sequence_number - 1);
1161
for (i = 0, j = 1; i < 13; i++, j+=2) {
1162
-    if (j == 11)
1163
-     j = 14;
1164
-    else if (j == 26)
1165
-     j = 28;
1166
+ if (j == 11)
1167
+ j = 14;
1168
+ else if (j == 26)
1169
+ j = 28;
1170
1171
-    if (pointer[j+1] == 0)
1172
-     lfn->name[offset + i] = pointer[j];
1173
-    else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1174
-     return -4;
1175
-    else
1176
-     lfn->name[offset + i] = 0;
1177
+ if (pointer[j+1] == 0)
1178
+ lfn->name[offset + i] = pointer[j];
1179
+ else if (pointer[j+1] != 0xff || (pointer[0] & 0x40) == 0)
1180
+ return -4;
1181
+ else
1182
+ lfn->name[offset + i] = 0;
1183
}
1184
1185
if (pointer[0] & 0x40)
1186
-    lfn->len = offset + strlen((char*)lfn->name + offset);
1187
+ lfn->len = offset + strlen((char*)lfn->name + offset);
1188
1189
return 0;
1190
}
1191
1192
/* returns 0 if successful, >0 if no short_name, and <0 on error */
1193
static int parse_short_name(BDRVVVFATState* s,
1194
-    long_file_name* lfn, direntry_t* direntry)
1195
+ long_file_name* lfn, direntry_t* direntry)
1196
{
1197
int i, j;
1198
1199
if (!is_short_name(direntry))
1200
-    return 1;
1201
+ return 1;
1202
1203
for (j = 7; j >= 0 && direntry->name[j] == ' '; j--);
1204
for (i = 0; i <= j; i++) {
1205
-    if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1206
-     return -1;
1207
-    else if (s->downcase_short_names)
1208
-     lfn->name[i] = qemu_tolower(direntry->name[i]);
1209
-    else
1210
-     lfn->name[i] = direntry->name[i];
1211
+ if (direntry->name[i] <= ' ' || direntry->name[i] > 0x7f)
1212
+ return -1;
1213
+ else if (s->downcase_short_names)
1214
+ lfn->name[i] = qemu_tolower(direntry->name[i]);
1215
+ else
1216
+ lfn->name[i] = direntry->name[i];
1217
}
1218
1219
for (j = 2; j >= 0 && direntry->name[8 + j] == ' '; j--) {
1220
}
1221
if (j >= 0) {
1222
-    lfn->name[i++] = '.';
1223
-    lfn->name[i + j + 1] = '\0';
1224
-    for (;j >= 0; j--) {
1225
+ lfn->name[i++] = '.';
1226
+ lfn->name[i + j + 1] = '\0';
1227
+ for (;j >= 0; j--) {
1228
uint8_t c = direntry->name[8 + j];
1229
if (c <= ' ' || c > 0x7f) {
1230
return -2;
1231
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
1232
} else {
1233
lfn->name[i + j] = c;
1234
}
1235
-    }
1236
+ }
1237
} else
1238
-    lfn->name[i + j + 1] = '\0';
1239
+ lfn->name[i + j + 1] = '\0';
1240
1241
lfn->len = strlen((char*)lfn->name);
1242
1243
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
1244
}
1245
1246
static inline uint32_t modified_fat_get(BDRVVVFATState* s,
1247
-    unsigned int cluster)
1248
+ unsigned int cluster)
1249
{
1250
if (cluster < s->last_cluster_of_root_directory) {
1251
-    if (cluster + 1 == s->last_cluster_of_root_directory)
1252
-     return s->max_fat_value;
1253
-    else
1254
-     return cluster + 1;
1255
+ if (cluster + 1 == s->last_cluster_of_root_directory)
1256
+ return s->max_fat_value;
1257
+ else
1258
+ return cluster + 1;
1259
}
1260
1261
if (s->fat_type==32) {
1262
@@ -XXX,XX +XXX,XX @@ static const char* get_basename(const char* path)
1263
{
1264
char* basename = strrchr(path, '/');
1265
if (basename == NULL)
1266
-    return path;
1267
+ return path;
1268
else
1269
-    return basename + 1; /* strip '/' */
1270
+ return basename + 1; /* strip '/' */
1271
}
1272
1273
/*
1274
@@ -XXX,XX +XXX,XX @@ typedef enum {
1275
* assumed to be *not* deleted (and *only* those).
1276
*/
1277
static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1278
-    direntry_t* direntry, const char* path)
1279
+ direntry_t* direntry, const char* path)
1280
{
1281
/*
1282
* This is a little bit tricky:
1283
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1284
1285
/* the root directory */
1286
if (cluster_num == 0)
1287
-    return 0;
1288
+ return 0;
1289
1290
/* write support */
1291
if (s->qcow) {
1292
-    basename2 = get_basename(path);
1293
+ basename2 = get_basename(path);
1294
1295
-    mapping = find_mapping_for_cluster(s, cluster_num);
1296
+ mapping = find_mapping_for_cluster(s, cluster_num);
1297
1298
-    if (mapping) {
1299
-     const char* basename;
1300
+ if (mapping) {
1301
+ const char* basename;
1302
1303
-     assert(mapping->mode & MODE_DELETED);
1304
-     mapping->mode &= ~MODE_DELETED;
1305
+ assert(mapping->mode & MODE_DELETED);
1306
+ mapping->mode &= ~MODE_DELETED;
1307
1308
-     basename = get_basename(mapping->path);
1309
+ basename = get_basename(mapping->path);
1310
1311
-     assert(mapping->mode & MODE_NORMAL);
1312
+ assert(mapping->mode & MODE_NORMAL);
1313
1314
-     /* rename */
1315
-     if (strcmp(basename, basename2))
1316
-        schedule_rename(s, cluster_num, g_strdup(path));
1317
-    } else if (is_file(direntry))
1318
-     /* new file */
1319
-     schedule_new_file(s, g_strdup(path), cluster_num);
1320
-    else {
1321
+ /* rename */
1322
+ if (strcmp(basename, basename2))
1323
+ schedule_rename(s, cluster_num, g_strdup(path));
1324
+ } else if (is_file(direntry))
1325
+ /* new file */
1326
+ schedule_new_file(s, g_strdup(path), cluster_num);
1327
+ else {
1328
abort();
1329
-     return 0;
1330
-    }
1331
+ return 0;
1332
+ }
1333
}
1334
1335
while(1) {
1336
-    if (s->qcow) {
1337
-     if (!copy_it && cluster_was_modified(s, cluster_num)) {
1338
-        if (mapping == NULL ||
1339
-            mapping->begin > cluster_num ||
1340
-            mapping->end <= cluster_num)
1341
-        mapping = find_mapping_for_cluster(s, cluster_num);
1342
+ if (s->qcow) {
1343
+ if (!copy_it && cluster_was_modified(s, cluster_num)) {
1344
+ if (mapping == NULL ||
1345
+ mapping->begin > cluster_num ||
1346
+ mapping->end <= cluster_num)
1347
+ mapping = find_mapping_for_cluster(s, cluster_num);
1348
1349
1350
-        if (mapping &&
1351
-            (mapping->mode & MODE_DIRECTORY) == 0) {
1352
+ if (mapping &&
1353
+ (mapping->mode & MODE_DIRECTORY) == 0) {
1354
1355
-         /* was modified in qcow */
1356
-         if (offset != mapping->info.file.offset + s->cluster_size
1357
-             * (cluster_num - mapping->begin)) {
1358
-            /* offset of this cluster in file chain has changed */
1359
+ /* was modified in qcow */
1360
+ if (offset != mapping->info.file.offset + s->cluster_size
1361
+ * (cluster_num - mapping->begin)) {
1362
+ /* offset of this cluster in file chain has changed */
1363
abort();
1364
-            copy_it = 1;
1365
-         } else if (offset == 0) {
1366
-            const char* basename = get_basename(mapping->path);
1367
+ copy_it = 1;
1368
+ } else if (offset == 0) {
1369
+ const char* basename = get_basename(mapping->path);
1370
1371
-            if (strcmp(basename, basename2))
1372
-             copy_it = 1;
1373
-            first_mapping_index = array_index(&(s->mapping), mapping);
1374
-         }
1375
+ if (strcmp(basename, basename2))
1376
+ copy_it = 1;
1377
+ first_mapping_index = array_index(&(s->mapping), mapping);
1378
+ }
1379
1380
-         if (mapping->first_mapping_index != first_mapping_index
1381
-             && mapping->info.file.offset > 0) {
1382
+ if (mapping->first_mapping_index != first_mapping_index
1383
+ && mapping->info.file.offset > 0) {
1384
abort();
1385
-            copy_it = 1;
1386
-         }
1387
-
1388
-         /* need to write out? */
1389
-         if (!was_modified && is_file(direntry)) {
1390
-            was_modified = 1;
1391
-            schedule_writeout(s, mapping->dir_index, offset);
1392
-         }
1393
-        }
1394
-     }
1395
-
1396
-     if (copy_it) {
1397
-        int i, dummy;
1398
-        /*
1399
-         * This is horribly inefficient, but that is okay, since
1400
-         * it is rarely executed, if at all.
1401
-         */
1402
-        int64_t offset = cluster2sector(s, cluster_num);
1403
-
1404
-        vvfat_close_current_file(s);
1405
+ copy_it = 1;
1406
+ }
1407
+
1408
+ /* need to write out? */
1409
+ if (!was_modified && is_file(direntry)) {
1410
+ was_modified = 1;
1411
+ schedule_writeout(s, mapping->dir_index, offset);
1412
+ }
1413
+ }
1414
+ }
1415
+
1416
+ if (copy_it) {
1417
+ int i, dummy;
1418
+ /*
1419
+ * This is horribly inefficient, but that is okay, since
1420
+ * it is rarely executed, if at all.
1421
+ */
1422
+ int64_t offset = cluster2sector(s, cluster_num);
1423
+
1424
+ vvfat_close_current_file(s);
1425
for (i = 0; i < s->sectors_per_cluster; i++) {
1426
int res;
1427
1428
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1429
}
1430
}
1431
}
1432
-     }
1433
-    }
1434
+ }
1435
+ }
1436
1437
-    ret++;
1438
-    if (s->used_clusters[cluster_num] & USED_ANY)
1439
-     return 0;
1440
-    s->used_clusters[cluster_num] = USED_FILE;
1441
+ ret++;
1442
+ if (s->used_clusters[cluster_num] & USED_ANY)
1443
+ return 0;
1444
+ s->used_clusters[cluster_num] = USED_FILE;
1445
1446
-    cluster_num = modified_fat_get(s, cluster_num);
1447
+ cluster_num = modified_fat_get(s, cluster_num);
1448
1449
-    if (fat_eof(s, cluster_num))
1450
-     return ret;
1451
-    else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1452
-     return -1;
1453
+ if (fat_eof(s, cluster_num))
1454
+ return ret;
1455
+ else if (cluster_num < 2 || cluster_num > s->max_fat_value - 16)
1456
+ return -1;
1457
1458
-    offset += s->cluster_size;
1459
+ offset += s->cluster_size;
1460
}
1461
}
1462
1463
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1464
* used by the directory, its subdirectories and their files.
1465
*/
1466
static int check_directory_consistency(BDRVVVFATState *s,
1467
-    int cluster_num, const char* path)
1468
+ int cluster_num, const char* path)
1469
{
1470
int ret = 0;
1471
unsigned char* cluster = g_malloc(s->cluster_size);
1472
@@ -XXX,XX +XXX,XX @@ static int check_directory_consistency(BDRVVVFATState *s,
1473
path2[path_len + 1] = '\0';
1474
1475
if (mapping) {
1476
-    const char* basename = get_basename(mapping->path);
1477
-    const char* basename2 = get_basename(path);
1478
+ const char* basename = get_basename(mapping->path);
1479
+ const char* basename2 = get_basename(path);
1480
1481
-    assert(mapping->mode & MODE_DIRECTORY);
1482
+ assert(mapping->mode & MODE_DIRECTORY);
1483
1484
-    assert(mapping->mode & MODE_DELETED);
1485
-    mapping->mode &= ~MODE_DELETED;
1486
+ assert(mapping->mode & MODE_DELETED);
1487
+ mapping->mode &= ~MODE_DELETED;
1488
1489
-    if (strcmp(basename, basename2))
1490
-     schedule_rename(s, cluster_num, g_strdup(path));
1491
+ if (strcmp(basename, basename2))
1492
+ schedule_rename(s, cluster_num, g_strdup(path));
1493
} else
1494
-    /* new directory */
1495
-    schedule_mkdir(s, cluster_num, g_strdup(path));
1496
+ /* new directory */
1497
+ schedule_mkdir(s, cluster_num, g_strdup(path));
1498
1499
lfn_init(&lfn);
1500
do {
1501
-    int i;
1502
-    int subret = 0;
1503
+ int i;
1504
+ int subret = 0;
1505
1506
-    ret++;
1507
+ ret++;
1508
1509
-    if (s->used_clusters[cluster_num] & USED_ANY) {
1510
-     fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1511
+ if (s->used_clusters[cluster_num] & USED_ANY) {
1512
+ fprintf(stderr, "cluster %d used more than once\n", (int)cluster_num);
1513
goto fail;
1514
-    }
1515
-    s->used_clusters[cluster_num] = USED_DIRECTORY;
1516
+ }
1517
+ s->used_clusters[cluster_num] = USED_DIRECTORY;
1518
1519
DLOG(fprintf(stderr, "read cluster %d (sector %d)\n", (int)cluster_num, (int)cluster2sector(s, cluster_num)));
1520
-    subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1521
-        s->sectors_per_cluster);
1522
-    if (subret) {
1523
-     fprintf(stderr, "Error fetching direntries\n");
1524
-    fail:
1525
+ subret = vvfat_read(s->bs, cluster2sector(s, cluster_num), cluster,
1526
+ s->sectors_per_cluster);
1527
+ if (subret) {
1528
+ fprintf(stderr, "Error fetching direntries\n");
1529
+ fail:
1530
g_free(cluster);
1531
-     return 0;
1532
-    }
1533
+ return 0;
1534
+ }
1535
1536
-    for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1537
-     int cluster_count = 0;
1538
+ for (i = 0; i < 0x10 * s->sectors_per_cluster; i++) {
1539
+ int cluster_count = 0;
1540
1541
DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i));
1542
-     if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1543
-         is_free(direntries + i))
1544
-        continue;
1545
-
1546
-     subret = parse_long_name(&lfn, direntries + i);
1547
-     if (subret < 0) {
1548
-        fprintf(stderr, "Error in long name\n");
1549
-        goto fail;
1550
-     }
1551
-     if (subret == 0 || is_free(direntries + i))
1552
-        continue;
1553
-
1554
-     if (fat_chksum(direntries+i) != lfn.checksum) {
1555
-        subret = parse_short_name(s, &lfn, direntries + i);
1556
-        if (subret < 0) {
1557
-         fprintf(stderr, "Error in short name (%d)\n", subret);
1558
-         goto fail;
1559
-        }
1560
-        if (subret > 0 || !strcmp((char*)lfn.name, ".")
1561
-            || !strcmp((char*)lfn.name, ".."))
1562
-         continue;
1563
-     }
1564
-     lfn.checksum = 0x100; /* cannot use long name twice */
1565
-
1566
-     if (path_len + 1 + lfn.len >= PATH_MAX) {
1567
-        fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1568
-        goto fail;
1569
-     }
1570
+ if (is_volume_label(direntries + i) || is_dot(direntries + i) ||
1571
+ is_free(direntries + i))
1572
+ continue;
1573
+
1574
+ subret = parse_long_name(&lfn, direntries + i);
1575
+ if (subret < 0) {
1576
+ fprintf(stderr, "Error in long name\n");
1577
+ goto fail;
1578
+ }
1579
+ if (subret == 0 || is_free(direntries + i))
1580
+ continue;
1581
+
1582
+ if (fat_chksum(direntries+i) != lfn.checksum) {
1583
+ subret = parse_short_name(s, &lfn, direntries + i);
1584
+ if (subret < 0) {
1585
+ fprintf(stderr, "Error in short name (%d)\n", subret);
1586
+ goto fail;
1587
+ }
1588
+ if (subret > 0 || !strcmp((char*)lfn.name, ".")
1589
+ || !strcmp((char*)lfn.name, ".."))
1590
+ continue;
1591
+ }
1592
+ lfn.checksum = 0x100; /* cannot use long name twice */
1593
+
1594
+ if (path_len + 1 + lfn.len >= PATH_MAX) {
1595
+ fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
1596
+ goto fail;
1597
+ }
1598
pstrcpy(path2 + path_len + 1, sizeof(path2) - path_len - 1,
1599
(char*)lfn.name);
1600
1601
-     if (is_directory(direntries + i)) {
1602
-        if (begin_of_direntry(direntries + i) == 0) {
1603
-         DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1604
-         goto fail;
1605
-        }
1606
-        cluster_count = check_directory_consistency(s,
1607
-            begin_of_direntry(direntries + i), path2);
1608
-        if (cluster_count == 0) {
1609
-         DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1610
-         goto fail;
1611
-        }
1612
-     } else if (is_file(direntries + i)) {
1613
-        /* check file size with FAT */
1614
-        cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1615
-        if (cluster_count !=
1616
+ if (is_directory(direntries + i)) {
1617
+ if (begin_of_direntry(direntries + i) == 0) {
1618
+ DLOG(fprintf(stderr, "invalid begin for directory: %s\n", path2); print_direntry(direntries + i));
1619
+ goto fail;
1620
+ }
1621
+ cluster_count = check_directory_consistency(s,
1622
+ begin_of_direntry(direntries + i), path2);
1623
+ if (cluster_count == 0) {
1624
+ DLOG(fprintf(stderr, "problem in directory %s:\n", path2); print_direntry(direntries + i));
1625
+ goto fail;
1626
+ }
1627
+ } else if (is_file(direntries + i)) {
1628
+ /* check file size with FAT */
1629
+ cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
1630
+ if (cluster_count !=
1631
DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
1632
-         DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1633
-         goto fail;
1634
-        }
1635
-     } else
1636
+ DLOG(fprintf(stderr, "Cluster count mismatch\n"));
1637
+ goto fail;
1638
+ }
1639
+ } else
1640
abort(); /* cluster_count = 0; */
1641
1642
-     ret += cluster_count;
1643
-    }
1644
+ ret += cluster_count;
1645
+ }
1646
1647
-    cluster_num = modified_fat_get(s, cluster_num);
1648
+ cluster_num = modified_fat_get(s, cluster_num);
1649
} while(!fat_eof(s, cluster_num));
1650
1651
g_free(cluster);
1652
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
1653
* - if all is fine, return number of used clusters
1654
*/
1655
if (s->fat2 == NULL) {
1656
-    int size = 0x200 * s->sectors_per_fat;
1657
-    s->fat2 = g_malloc(size);
1658
-    memcpy(s->fat2, s->fat.pointer, size);
1659
+ int size = 0x200 * s->sectors_per_fat;
1660
+ s->fat2 = g_malloc(size);
1661
+ memcpy(s->fat2, s->fat.pointer, size);
1662
}
1663
check = vvfat_read(s->bs,
1664
-     s->first_sectors_number, s->fat2, s->sectors_per_fat);
1665
+ s->first_sectors_number, s->fat2, s->sectors_per_fat);
1666
if (check) {
1667
-    fprintf(stderr, "Could not copy fat\n");
1668
-    return 0;
1669
+ fprintf(stderr, "Could not copy fat\n");
1670
+ return 0;
1671
}
1672
assert (s->used_clusters);
1673
for (i = 0; i < sector2cluster(s, s->sector_count); i++)
1674
-    s->used_clusters[i] &= ~USED_ANY;
1675
+ s->used_clusters[i] &= ~USED_ANY;
1676
1677
clear_commits(s);
1678
1679
/* mark every mapped file/directory as deleted.
1680
* (check_directory_consistency() will unmark those still present). */
1681
if (s->qcow)
1682
-    for (i = 0; i < s->mapping.next; i++) {
1683
-     mapping_t* mapping = array_get(&(s->mapping), i);
1684
-     if (mapping->first_mapping_index < 0)
1685
-        mapping->mode |= MODE_DELETED;
1686
-    }
1687
+ for (i = 0; i < s->mapping.next; i++) {
1688
+ mapping_t* mapping = array_get(&(s->mapping), i);
1689
+ if (mapping->first_mapping_index < 0)
1690
+ mapping->mode |= MODE_DELETED;
1691
+ }
1692
1693
used_clusters_count = check_directory_consistency(s, 0, s->path);
1694
if (used_clusters_count <= 0) {
1695
-    DLOG(fprintf(stderr, "problem in directory\n"));
1696
-    return 0;
1697
+ DLOG(fprintf(stderr, "problem in directory\n"));
1698
+ return 0;
1699
}
1700
1701
check = s->last_cluster_of_root_directory;
1702
for (i = check; i < sector2cluster(s, s->sector_count); i++) {
1703
-    if (modified_fat_get(s, i)) {
1704
-     if(!s->used_clusters[i]) {
1705
-        DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1706
-        return 0;
1707
-     }
1708
-     check++;
1709
-    }
1710
+ if (modified_fat_get(s, i)) {
1711
+ if(!s->used_clusters[i]) {
1712
+ DLOG(fprintf(stderr, "FAT was modified (%d), but cluster is not used?\n", i));
1713
+ return 0;
1714
+ }
1715
+ check++;
1716
+ }
1717
1718
-    if (s->used_clusters[i] == USED_ALLOCATED) {
1719
-     /* allocated, but not used... */
1720
-     DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1721
-     return 0;
1722
-    }
1723
+ if (s->used_clusters[i] == USED_ALLOCATED) {
1724
+ /* allocated, but not used... */
1725
+ DLOG(fprintf(stderr, "unused, modified cluster: %d\n", i));
1726
+ return 0;
1727
+ }
1728
}
1729
1730
if (check != used_clusters_count)
1731
-    return 0;
1732
+ return 0;
1733
1734
return used_clusters_count;
1735
}
1736
1737
static inline void adjust_mapping_indices(BDRVVVFATState* s,
1738
-    int offset, int adjust)
1739
+ int offset, int adjust)
1740
{
1741
int i;
1742
1743
for (i = 0; i < s->mapping.next; i++) {
1744
-    mapping_t* mapping = array_get(&(s->mapping), i);
1745
+ mapping_t* mapping = array_get(&(s->mapping), i);
1746
1747
#define ADJUST_MAPPING_INDEX(name) \
1748
-    if (mapping->name >= offset) \
1749
-     mapping->name += adjust
1750
+ if (mapping->name >= offset) \
1751
+ mapping->name += adjust
1752
1753
-    ADJUST_MAPPING_INDEX(first_mapping_index);
1754
-    if (mapping->mode & MODE_DIRECTORY)
1755
-     ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1756
+ ADJUST_MAPPING_INDEX(first_mapping_index);
1757
+ if (mapping->mode & MODE_DIRECTORY)
1758
+ ADJUST_MAPPING_INDEX(info.dir.parent_mapping_index);
1759
}
1760
}
1761
1762
/* insert or update mapping */
1763
static mapping_t* insert_mapping(BDRVVVFATState* s,
1764
-    uint32_t begin, uint32_t end)
1765
+ uint32_t begin, uint32_t end)
1766
{
1767
/*
1768
* - find mapping where mapping->begin >= begin,
1769
@@ -XXX,XX +XXX,XX @@ static mapping_t* insert_mapping(BDRVVVFATState* s,
1770
mapping_t* first_mapping = array_get(&(s->mapping), 0);
1771
1772
if (index < s->mapping.next && (mapping = array_get(&(s->mapping), index))
1773
-     && mapping->begin < begin) {
1774
-    mapping->end = begin;
1775
-    index++;
1776
-    mapping = array_get(&(s->mapping), index);
1777
+ && mapping->begin < begin) {
1778
+ mapping->end = begin;
1779
+ index++;
1780
+ mapping = array_get(&(s->mapping), index);
1781
}
1782
if (index >= s->mapping.next || mapping->begin > begin) {
1783
-    mapping = array_insert(&(s->mapping), index, 1);
1784
-    mapping->path = NULL;
1785
-    adjust_mapping_indices(s, index, +1);
1786
+ mapping = array_insert(&(s->mapping), index, 1);
1787
+ mapping->path = NULL;
1788
+ adjust_mapping_indices(s, index, +1);
1789
}
1790
1791
mapping->begin = begin;
1792
@@ -XXX,XX +XXX,XX @@ assert(index + 1 >= s->mapping.next ||
1793
next_mapping->begin >= end)));
1794
1795
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1796
-    s->current_mapping = array_get(&(s->mapping),
1797
-        s->current_mapping - first_mapping);
1798
+ s->current_mapping = array_get(&(s->mapping),
1799
+ s->current_mapping - first_mapping);
1800
1801
return mapping;
1802
}
1803
@@ -XXX,XX +XXX,XX @@ static int remove_mapping(BDRVVVFATState* s, int mapping_index)
1804
adjust_mapping_indices(s, mapping_index, -1);
1805
1806
if (s->current_mapping && first_mapping != (mapping_t*)s->mapping.pointer)
1807
-    s->current_mapping = array_get(&(s->mapping),
1808
-        s->current_mapping - first_mapping);
1809
+ s->current_mapping = array_get(&(s->mapping),
1810
+ s->current_mapping - first_mapping);
1811
1812
return 0;
1813
}
1814
@@ -XXX,XX +XXX,XX @@ static void adjust_dirindices(BDRVVVFATState* s, int offset, int adjust)
1815
{
1816
int i;
1817
for (i = 0; i < s->mapping.next; i++) {
1818
-    mapping_t* mapping = array_get(&(s->mapping), i);
1819
-    if (mapping->dir_index >= offset)
1820
-     mapping->dir_index += adjust;
1821
-    if ((mapping->mode & MODE_DIRECTORY) &&
1822
-        mapping->info.dir.first_dir_index >= offset)
1823
-     mapping->info.dir.first_dir_index += adjust;
1824
+ mapping_t* mapping = array_get(&(s->mapping), i);
1825
+ if (mapping->dir_index >= offset)
1826
+ mapping->dir_index += adjust;
1827
+ if ((mapping->mode & MODE_DIRECTORY) &&
1828
+ mapping->info.dir.first_dir_index >= offset)
1829
+ mapping->info.dir.first_dir_index += adjust;
1830
}
1831
}
1832
1833
static direntry_t* insert_direntries(BDRVVVFATState* s,
1834
-    int dir_index, int count)
1835
+ int dir_index, int count)
1836
{
1837
/*
1838
* make room in s->directory,
1839
@@ -XXX,XX +XXX,XX @@ static direntry_t* insert_direntries(BDRVVVFATState* s,
1840
*/
1841
direntry_t* result = array_insert(&(s->directory), dir_index, count);
1842
if (result == NULL)
1843
-    return NULL;
1844
+ return NULL;
1845
adjust_dirindices(s, dir_index, count);
1846
return result;
1847
}
1848
@@ -XXX,XX +XXX,XX @@ static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
1849
{
1850
int ret = array_remove_slice(&(s->directory), dir_index, count);
1851
if (ret)
1852
-    return ret;
1853
+ return ret;
1854
adjust_dirindices(s, dir_index, -count);
1855
return 0;
1856
}
1857
@@ -XXX,XX +XXX,XX @@ static int remove_direntries(BDRVVVFATState* s, int dir_index, int count)
1858
* adjusted)
1859
*/
1860
static int commit_mappings(BDRVVVFATState* s,
1861
-    uint32_t first_cluster, int dir_index)
1862
+ uint32_t first_cluster, int dir_index)
1863
{
1864
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
1865
direntry_t* direntry = array_get(&(s->directory), dir_index);
1866
@@ -XXX,XX +XXX,XX @@ static int commit_mappings(BDRVVVFATState* s,
1867
mapping->first_mapping_index = -1;
1868
mapping->dir_index = dir_index;
1869
mapping->mode = (dir_index <= 0 || is_directory(direntry)) ?
1870
-    MODE_DIRECTORY : MODE_NORMAL;
1871
+ MODE_DIRECTORY : MODE_NORMAL;
1872
1873
while (!fat_eof(s, cluster)) {
1874
-    uint32_t c, c1;
1875
-
1876
-    for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
1877
-        c = c1, c1 = modified_fat_get(s, c1));
1878
-
1879
-    c++;
1880
-    if (c > mapping->end) {
1881
-     int index = array_index(&(s->mapping), mapping);
1882
-     int i, max_i = s->mapping.next - index;
1883
-     for (i = 1; i < max_i && mapping[i].begin < c; i++);
1884
-     while (--i > 0)
1885
-        remove_mapping(s, index + 1);
1886
-    }
1887
-    assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
1888
-        || mapping[1].begin >= c);
1889
-    mapping->end = c;
1890
-
1891
-    if (!fat_eof(s, c1)) {
1892
-     int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
1893
-     mapping_t* next_mapping = i >= s->mapping.next ? NULL :
1894
-        array_get(&(s->mapping), i);
1895
-
1896
-     if (next_mapping == NULL || next_mapping->begin > c1) {
1897
-        int i1 = array_index(&(s->mapping), mapping);
1898
-
1899
-        next_mapping = insert_mapping(s, c1, c1+1);
1900
-
1901
-        if (c1 < c)
1902
-         i1++;
1903
-        mapping = array_get(&(s->mapping), i1);
1904
-     }
1905
-
1906
-     next_mapping->dir_index = mapping->dir_index;
1907
-     next_mapping->first_mapping_index =
1908
-        mapping->first_mapping_index < 0 ?
1909
-        array_index(&(s->mapping), mapping) :
1910
-        mapping->first_mapping_index;
1911
-     next_mapping->path = mapping->path;
1912
-     next_mapping->mode = mapping->mode;
1913
-     next_mapping->read_only = mapping->read_only;
1914
-     if (mapping->mode & MODE_DIRECTORY) {
1915
-        next_mapping->info.dir.parent_mapping_index =
1916
-            mapping->info.dir.parent_mapping_index;
1917
-        next_mapping->info.dir.first_dir_index =
1918
-            mapping->info.dir.first_dir_index +
1919
-            0x10 * s->sectors_per_cluster *
1920
-            (mapping->end - mapping->begin);
1921
-     } else
1922
-        next_mapping->info.file.offset = mapping->info.file.offset +
1923
-            mapping->end - mapping->begin;
1924
-
1925
-     mapping = next_mapping;
1926
-    }
1927
-
1928
-    cluster = c1;
1929
+ uint32_t c, c1;
1930
+
1931
+ for (c = cluster, c1 = modified_fat_get(s, c); c + 1 == c1;
1932
+ c = c1, c1 = modified_fat_get(s, c1));
1933
+
1934
+ c++;
1935
+ if (c > mapping->end) {
1936
+ int index = array_index(&(s->mapping), mapping);
1937
+ int i, max_i = s->mapping.next - index;
1938
+ for (i = 1; i < max_i && mapping[i].begin < c; i++);
1939
+ while (--i > 0)
1940
+ remove_mapping(s, index + 1);
1941
+ }
1942
+ assert(mapping == array_get(&(s->mapping), s->mapping.next - 1)
1943
+ || mapping[1].begin >= c);
1944
+ mapping->end = c;
1945
+
1946
+ if (!fat_eof(s, c1)) {
1947
+ int i = find_mapping_for_cluster_aux(s, c1, 0, s->mapping.next);
1948
+ mapping_t* next_mapping = i >= s->mapping.next ? NULL :
1949
+ array_get(&(s->mapping), i);
1950
+
1951
+ if (next_mapping == NULL || next_mapping->begin > c1) {
1952
+ int i1 = array_index(&(s->mapping), mapping);
1953
+
1954
+ next_mapping = insert_mapping(s, c1, c1+1);
1955
+
1956
+ if (c1 < c)
1957
+ i1++;
1958
+ mapping = array_get(&(s->mapping), i1);
1959
+ }
1960
+
1961
+ next_mapping->dir_index = mapping->dir_index;
1962
+ next_mapping->first_mapping_index =
1963
+ mapping->first_mapping_index < 0 ?
1964
+ array_index(&(s->mapping), mapping) :
1965
+ mapping->first_mapping_index;
1966
+ next_mapping->path = mapping->path;
1967
+ next_mapping->mode = mapping->mode;
1968
+ next_mapping->read_only = mapping->read_only;
1969
+ if (mapping->mode & MODE_DIRECTORY) {
1970
+ next_mapping->info.dir.parent_mapping_index =
1971
+ mapping->info.dir.parent_mapping_index;
1972
+ next_mapping->info.dir.first_dir_index =
1973
+ mapping->info.dir.first_dir_index +
1974
+ 0x10 * s->sectors_per_cluster *
1975
+ (mapping->end - mapping->begin);
1976
+ } else
1977
+ next_mapping->info.file.offset = mapping->info.file.offset +
1978
+ mapping->end - mapping->begin;
1979
+
1980
+ mapping = next_mapping;
1981
+ }
1982
+
1983
+ cluster = c1;
1984
}
1985
1986
return 0;
1987
}
1988
1989
static int commit_direntries(BDRVVVFATState* s,
1990
-    int dir_index, int parent_mapping_index)
1991
+ int dir_index, int parent_mapping_index)
1992
{
1993
direntry_t* direntry = array_get(&(s->directory), dir_index);
1994
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
1995
@@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp
1996
mapping->info.dir.parent_mapping_index = parent_mapping_index;
1997
1998
if (first_cluster == 0) {
1999
-    old_cluster_count = new_cluster_count =
2000
-     s->last_cluster_of_root_directory;
2001
+ old_cluster_count = new_cluster_count =
2002
+ s->last_cluster_of_root_directory;
2003
} else {
2004
-    for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2005
-        c = fat_get(s, c))
2006
-     old_cluster_count++;
2007
+ for (old_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2008
+ c = fat_get(s, c))
2009
+ old_cluster_count++;
2010
2011
-    for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2012
-        c = modified_fat_get(s, c))
2013
-     new_cluster_count++;
2014
+ for (new_cluster_count = 0, c = first_cluster; !fat_eof(s, c);
2015
+ c = modified_fat_get(s, c))
2016
+ new_cluster_count++;
2017
}
2018
2019
if (new_cluster_count > old_cluster_count) {
2020
-    if (insert_direntries(s,
2021
-        current_dir_index + factor * old_cluster_count,
2022
-        factor * (new_cluster_count - old_cluster_count)) == NULL)
2023
-     return -1;
2024
+ if (insert_direntries(s,
2025
+ current_dir_index + factor * old_cluster_count,
2026
+ factor * (new_cluster_count - old_cluster_count)) == NULL)
2027
+ return -1;
2028
} else if (new_cluster_count < old_cluster_count)
2029
-    remove_direntries(s,
2030
-        current_dir_index + factor * new_cluster_count,
2031
-        factor * (old_cluster_count - new_cluster_count));
2032
+ remove_direntries(s,
2033
+ current_dir_index + factor * new_cluster_count,
2034
+ factor * (old_cluster_count - new_cluster_count));
2035
2036
for (c = first_cluster; !fat_eof(s, c); c = modified_fat_get(s, c)) {
2037
direntry_t *first_direntry;
2038
-    void* direntry = array_get(&(s->directory), current_dir_index);
2039
-    int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2040
-        s->sectors_per_cluster);
2041
-    if (ret)
2042
-     return ret;
2043
+ void* direntry = array_get(&(s->directory), current_dir_index);
2044
+ int ret = vvfat_read(s->bs, cluster2sector(s, c), direntry,
2045
+ s->sectors_per_cluster);
2046
+ if (ret)
2047
+ return ret;
2048
2049
/* The first directory entry on the filesystem is the volume name */
2050
first_direntry = (direntry_t*) s->directory.pointer;
2051
assert(!memcmp(first_direntry->name, s->volume_label, 11));
2052
2053
-    current_dir_index += factor;
2054
+ current_dir_index += factor;
2055
}
2056
2057
ret = commit_mappings(s, first_cluster, dir_index);
2058
if (ret)
2059
-    return ret;
2060
+ return ret;
2061
2062
/* recurse */
2063
for (i = 0; i < factor * new_cluster_count; i++) {
2064
-    direntry = array_get(&(s->directory), first_dir_index + i);
2065
-    if (is_directory(direntry) && !is_dot(direntry)) {
2066
-     mapping = find_mapping_for_cluster(s, first_cluster);
2067
-     assert(mapping->mode & MODE_DIRECTORY);
2068
-     ret = commit_direntries(s, first_dir_index + i,
2069
-        array_index(&(s->mapping), mapping));
2070
-     if (ret)
2071
-        return ret;
2072
-    }
2073
+ direntry = array_get(&(s->directory), first_dir_index + i);
2074
+ if (is_directory(direntry) && !is_dot(direntry)) {
2075
+ mapping = find_mapping_for_cluster(s, first_cluster);
2076
+ assert(mapping->mode & MODE_DIRECTORY);
2077
+ ret = commit_direntries(s, first_dir_index + i,
2078
+ array_index(&(s->mapping), mapping));
2079
+ if (ret)
2080
+ return ret;
2081
+ }
2082
}
2083
2084
return 0;
2085
@@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp
2086
/* commit one file (adjust contents, adjust mapping),
2087
return first_mapping_index */
2088
static int commit_one_file(BDRVVVFATState* s,
2089
-    int dir_index, uint32_t offset)
2090
+ int dir_index, uint32_t offset)
2091
{
2092
direntry_t* direntry = array_get(&(s->directory), dir_index);
2093
uint32_t c = begin_of_direntry(direntry);
2094
@@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s,
2095
assert((offset % s->cluster_size) == 0);
2096
2097
for (i = s->cluster_size; i < offset; i += s->cluster_size)
2098
-    c = modified_fat_get(s, c);
2099
+ c = modified_fat_get(s, c);
2100
2101
fd = qemu_open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
2102
if (fd < 0) {
2103
-    fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2104
-        strerror(errno), errno);
2105
+ fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
2106
+ strerror(errno), errno);
2107
g_free(cluster);
2108
-    return fd;
2109
+ return fd;
2110
}
2111
if (offset > 0) {
2112
if (lseek(fd, offset, SEEK_SET) != offset) {
2113
@@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s,
2114
}
2115
2116
while (offset < size) {
2117
-    uint32_t c1;
2118
-    int rest_size = (size - offset > s->cluster_size ?
2119
-        s->cluster_size : size - offset);
2120
-    int ret;
2121
+ uint32_t c1;
2122
+ int rest_size = (size - offset > s->cluster_size ?
2123
+ s->cluster_size : size - offset);
2124
+ int ret;
2125
2126
-    c1 = modified_fat_get(s, c);
2127
+ c1 = modified_fat_get(s, c);
2128
2129
-    assert((size - offset == 0 && fat_eof(s, c)) ||
2130
-        (size > offset && c >=2 && !fat_eof(s, c)));
2131
+ assert((size - offset == 0 && fat_eof(s, c)) ||
2132
+ (size > offset && c >=2 && !fat_eof(s, c)));
2133
2134
-    ret = vvfat_read(s->bs, cluster2sector(s, c),
2135
-     (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2136
+ ret = vvfat_read(s->bs, cluster2sector(s, c),
2137
+ (uint8_t*)cluster, (rest_size + 0x1ff) / 0x200);
2138
2139
if (ret < 0) {
2140
qemu_close(fd);
2141
@@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s,
2142
return -2;
2143
}
2144
2145
-    offset += rest_size;
2146
-    c = c1;
2147
+ offset += rest_size;
2148
+ c = c1;
2149
}
2150
2151
if (ftruncate(fd, size)) {
2152
@@ -XXX,XX +XXX,XX @@ static void check1(BDRVVVFATState* s)
2153
{
2154
int i;
2155
for (i = 0; i < s->mapping.next; i++) {
2156
-    mapping_t* mapping = array_get(&(s->mapping), i);
2157
-    if (mapping->mode & MODE_DELETED) {
2158
-     fprintf(stderr, "deleted\n");
2159
-     continue;
2160
-    }
2161
-    assert(mapping->dir_index < s->directory.next);
2162
-    direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2163
-    assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2164
-    if (mapping->mode & MODE_DIRECTORY) {
2165
-     assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2166
-     assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2167
-    }
2168
+ mapping_t* mapping = array_get(&(s->mapping), i);
2169
+ if (mapping->mode & MODE_DELETED) {
2170
+ fprintf(stderr, "deleted\n");
2171
+ continue;
2172
+ }
2173
+ assert(mapping->dir_index < s->directory.next);
2174
+ direntry_t* direntry = array_get(&(s->directory), mapping->dir_index);
2175
+ assert(mapping->begin == begin_of_direntry(direntry) || mapping->first_mapping_index >= 0);
2176
+ if (mapping->mode & MODE_DIRECTORY) {
2177
+ assert(mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster * (mapping->end - mapping->begin) <= s->directory.next);
2178
+ assert((mapping->info.dir.first_dir_index % (0x10 * s->sectors_per_cluster)) == 0);
2179
+ }
2180
}
2181
}
2182
2183
@@ -XXX,XX +XXX,XX @@ static void check2(BDRVVVFATState* s)
2184
int first_mapping = -1;
2185
2186
for (i = 0; i < s->directory.next; i++) {
2187
-    direntry_t* direntry = array_get(&(s->directory), i);
2188
-
2189
-    if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2190
-     mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2191
-     assert(mapping);
2192
-     assert(mapping->dir_index == i || is_dot(direntry));
2193
-     assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2194
-    }
2195
-
2196
-    if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2197
-     /* cluster start */
2198
-     int j, count = 0;
2199
-
2200
-     for (j = 0; j < s->mapping.next; j++) {
2201
-        mapping_t* mapping = array_get(&(s->mapping), j);
2202
-        if (mapping->mode & MODE_DELETED)
2203
-         continue;
2204
-        if (mapping->mode & MODE_DIRECTORY) {
2205
-         if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2206
-            assert(++count == 1);
2207
-            if (mapping->first_mapping_index == -1)
2208
-             first_mapping = array_index(&(s->mapping), mapping);
2209
-            else
2210
-             assert(first_mapping == mapping->first_mapping_index);
2211
-            if (mapping->info.dir.parent_mapping_index < 0)
2212
-             assert(j == 0);
2213
-            else {
2214
-             mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2215
-             assert(parent->mode & MODE_DIRECTORY);
2216
-             assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2217
-            }
2218
-         }
2219
-        }
2220
-     }
2221
-     if (count == 0)
2222
-        first_mapping = -1;
2223
-    }
2224
+ direntry_t* direntry = array_get(&(s->directory), i);
2225
+
2226
+ if (is_short_name(direntry) && begin_of_direntry(direntry)) {
2227
+ mapping_t* mapping = find_mapping_for_cluster(s, begin_of_direntry(direntry));
2228
+ assert(mapping);
2229
+ assert(mapping->dir_index == i || is_dot(direntry));
2230
+ assert(mapping->begin == begin_of_direntry(direntry) || is_dot(direntry));
2231
+ }
2232
+
2233
+ if ((i % (0x10 * s->sectors_per_cluster)) == 0) {
2234
+ /* cluster start */
2235
+ int j, count = 0;
2236
+
2237
+ for (j = 0; j < s->mapping.next; j++) {
2238
+ mapping_t* mapping = array_get(&(s->mapping), j);
2239
+ if (mapping->mode & MODE_DELETED)
2240
+ continue;
2241
+ if (mapping->mode & MODE_DIRECTORY) {
2242
+ if (mapping->info.dir.first_dir_index <= i && mapping->info.dir.first_dir_index + 0x10 * s->sectors_per_cluster > i) {
2243
+ assert(++count == 1);
2244
+ if (mapping->first_mapping_index == -1)
2245
+ first_mapping = array_index(&(s->mapping), mapping);
2246
+ else
2247
+ assert(first_mapping == mapping->first_mapping_index);
2248
+ if (mapping->info.dir.parent_mapping_index < 0)
2249
+ assert(j == 0);
2250
+ else {
2251
+ mapping_t* parent = array_get(&(s->mapping), mapping->info.dir.parent_mapping_index);
2252
+ assert(parent->mode & MODE_DIRECTORY);
2253
+ assert(parent->info.dir.first_dir_index < mapping->info.dir.first_dir_index);
2254
+ }
2255
+ }
2256
+ }
2257
+ }
2258
+ if (count == 0)
2259
+ first_mapping = -1;
2260
+ }
2261
}
2262
}
2263
#endif
2264
@@ -XXX,XX +XXX,XX @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2265
#ifdef DEBUG
2266
fprintf(stderr, "handle_renames\n");
2267
for (i = 0; i < s->commits.next; i++) {
2268
-    commit_t* commit = array_get(&(s->commits), i);
2269
-    fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2270
+ commit_t* commit = array_get(&(s->commits), i);
2271
+ fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
2272
}
2273
#endif
2274
2275
for (i = 0; i < s->commits.next;) {
2276
-    commit_t* commit = array_get(&(s->commits), i);
2277
-    if (commit->action == ACTION_RENAME) {
2278
-     mapping_t* mapping = find_mapping_for_cluster(s,
2279
-         commit->param.rename.cluster);
2280
-     char* old_path = mapping->path;
2281
-
2282
-     assert(commit->path);
2283
-     mapping->path = commit->path;
2284
-     if (rename(old_path, mapping->path))
2285
-        return -2;
2286
-
2287
-     if (mapping->mode & MODE_DIRECTORY) {
2288
-        int l1 = strlen(mapping->path);
2289
-        int l2 = strlen(old_path);
2290
-        int diff = l1 - l2;
2291
-        direntry_t* direntry = array_get(&(s->directory),
2292
-            mapping->info.dir.first_dir_index);
2293
-        uint32_t c = mapping->begin;
2294
-        int i = 0;
2295
-
2296
-        /* recurse */
2297
-        while (!fat_eof(s, c)) {
2298
-         do {
2299
-            direntry_t* d = direntry + i;
2300
-
2301
-            if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2302
-             mapping_t* m = find_mapping_for_cluster(s,
2303
-                 begin_of_direntry(d));
2304
-             int l = strlen(m->path);
2305
-             char* new_path = g_malloc(l + diff + 1);
2306
-
2307
-             assert(!strncmp(m->path, mapping->path, l2));
2308
+ commit_t* commit = array_get(&(s->commits), i);
2309
+ if (commit->action == ACTION_RENAME) {
2310
+ mapping_t* mapping = find_mapping_for_cluster(s,
2311
+ commit->param.rename.cluster);
2312
+ char* old_path = mapping->path;
2313
+
2314
+ assert(commit->path);
2315
+ mapping->path = commit->path;
2316
+ if (rename(old_path, mapping->path))
2317
+ return -2;
2318
+
2319
+ if (mapping->mode & MODE_DIRECTORY) {
2320
+ int l1 = strlen(mapping->path);
2321
+ int l2 = strlen(old_path);
2322
+ int diff = l1 - l2;
2323
+ direntry_t* direntry = array_get(&(s->directory),
2324
+ mapping->info.dir.first_dir_index);
2325
+ uint32_t c = mapping->begin;
2326
+ int i = 0;
2327
+
2328
+ /* recurse */
2329
+ while (!fat_eof(s, c)) {
2330
+ do {
2331
+ direntry_t* d = direntry + i;
2332
+
2333
+ if (is_file(d) || (is_directory(d) && !is_dot(d))) {
2334
+ mapping_t* m = find_mapping_for_cluster(s,
2335
+ begin_of_direntry(d));
2336
+ int l = strlen(m->path);
2337
+ char* new_path = g_malloc(l + diff + 1);
2338
+
2339
+ assert(!strncmp(m->path, mapping->path, l2));
2340
2341
pstrcpy(new_path, l + diff + 1, mapping->path);
2342
pstrcpy(new_path + l1, l + diff + 1 - l1,
2343
m->path + l2);
2344
2345
-             schedule_rename(s, m->begin, new_path);
2346
-            }
2347
-            i++;
2348
-         } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2349
-         c = fat_get(s, c);
2350
-        }
2351
-     }
2352
+ schedule_rename(s, m->begin, new_path);
2353
+ }
2354
+ i++;
2355
+ } while((i % (0x10 * s->sectors_per_cluster)) != 0);
2356
+ c = fat_get(s, c);
2357
+ }
2358
+ }
2359
2360
g_free(old_path);
2361
-     array_remove(&(s->commits), i);
2362
-     continue;
2363
-    } else if (commit->action == ACTION_MKDIR) {
2364
-     mapping_t* mapping;
2365
-     int j, parent_path_len;
2366
+ array_remove(&(s->commits), i);
2367
+ continue;
2368
+ } else if (commit->action == ACTION_MKDIR) {
2369
+ mapping_t* mapping;
2370
+ int j, parent_path_len;
2371
2372
#ifdef __MINGW32__
2373
if (mkdir(commit->path))
2374
@@ -XXX,XX +XXX,XX @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
2375
return -5;
2376
#endif
2377
2378
-     mapping = insert_mapping(s, commit->param.mkdir.cluster,
2379
-         commit->param.mkdir.cluster + 1);
2380
-     if (mapping == NULL)
2381
-        return -6;
2382
-
2383
-     mapping->mode = MODE_DIRECTORY;
2384
-     mapping->read_only = 0;
2385
-     mapping->path = commit->path;
2386
-     j = s->directory.next;
2387
-     assert(j);
2388
-     insert_direntries(s, s->directory.next,
2389
-         0x10 * s->sectors_per_cluster);
2390
-     mapping->info.dir.first_dir_index = j;
2391
-
2392
-     parent_path_len = strlen(commit->path)
2393
-        - strlen(get_basename(commit->path)) - 1;
2394
-     for (j = 0; j < s->mapping.next; j++) {
2395
-        mapping_t* m = array_get(&(s->mapping), j);
2396
-        if (m->first_mapping_index < 0 && m != mapping &&
2397
-            !strncmp(m->path, mapping->path, parent_path_len) &&
2398
-            strlen(m->path) == parent_path_len)
2399
-         break;
2400
-     }
2401
-     assert(j < s->mapping.next);
2402
-     mapping->info.dir.parent_mapping_index = j;
2403
-
2404
-     array_remove(&(s->commits), i);
2405
-     continue;
2406
-    }
2407
-
2408
-    i++;
2409
+ mapping = insert_mapping(s, commit->param.mkdir.cluster,
2410
+ commit->param.mkdir.cluster + 1);
2411
+ if (mapping == NULL)
2412
+ return -6;
2413
+
2414
+ mapping->mode = MODE_DIRECTORY;
2415
+ mapping->read_only = 0;
2416
+ mapping->path = commit->path;
2417
+ j = s->directory.next;
2418
+ assert(j);
2419
+ insert_direntries(s, s->directory.next,
2420
+ 0x10 * s->sectors_per_cluster);
2421
+ mapping->info.dir.first_dir_index = j;
2422
+
2423
+ parent_path_len = strlen(commit->path)
2424
+ - strlen(get_basename(commit->path)) - 1;
2425
+ for (j = 0; j < s->mapping.next; j++) {
2426
+ mapping_t* m = array_get(&(s->mapping), j);
2427
+ if (m->first_mapping_index < 0 && m != mapping &&
2428
+ !strncmp(m->path, mapping->path, parent_path_len) &&
2429
+ strlen(m->path) == parent_path_len)
2430
+ break;
2431
+ }
2432
+ assert(j < s->mapping.next);
2433
+ mapping->info.dir.parent_mapping_index = j;
2434
+
2435
+ array_remove(&(s->commits), i);
2436
+ continue;
2437
+ }
2438
+
2439
+ i++;
2440
}
2441
return 0;
2442
}
2443
@@ -XXX,XX +XXX,XX @@ static int handle_commits(BDRVVVFATState* s)
2444
vvfat_close_current_file(s);
2445
2446
for (i = 0; !fail && i < s->commits.next; i++) {
2447
-    commit_t* commit = array_get(&(s->commits), i);
2448
-    switch(commit->action) {
2449
-    case ACTION_RENAME: case ACTION_MKDIR:
2450
+ commit_t* commit = array_get(&(s->commits), i);
2451
+ switch(commit->action) {
2452
+ case ACTION_RENAME: case ACTION_MKDIR:
2453
abort();
2454
-     fail = -2;
2455
-     break;
2456
-    case ACTION_WRITEOUT: {
2457
+ fail = -2;
2458
+ break;
2459
+ case ACTION_WRITEOUT: {
2460
#ifndef NDEBUG
2461
/* these variables are only used by assert() below */
2462
-     direntry_t* entry = array_get(&(s->directory),
2463
-         commit->param.writeout.dir_index);
2464
-     uint32_t begin = begin_of_direntry(entry);
2465
-     mapping_t* mapping = find_mapping_for_cluster(s, begin);
2466
+ direntry_t* entry = array_get(&(s->directory),
2467
+ commit->param.writeout.dir_index);
2468
+ uint32_t begin = begin_of_direntry(entry);
2469
+ mapping_t* mapping = find_mapping_for_cluster(s, begin);
2470
#endif
2471
2472
-     assert(mapping);
2473
-     assert(mapping->begin == begin);
2474
-     assert(commit->path == NULL);
2475
-
2476
-     if (commit_one_file(s, commit->param.writeout.dir_index,
2477
-            commit->param.writeout.modified_offset))
2478
-        fail = -3;
2479
-
2480
-     break;
2481
-    }
2482
-    case ACTION_NEW_FILE: {
2483
-     int begin = commit->param.new_file.first_cluster;
2484
-     mapping_t* mapping = find_mapping_for_cluster(s, begin);
2485
-     direntry_t* entry;
2486
-     int i;
2487
-
2488
-     /* find direntry */
2489
-     for (i = 0; i < s->directory.next; i++) {
2490
-        entry = array_get(&(s->directory), i);
2491
-        if (is_file(entry) && begin_of_direntry(entry) == begin)
2492
-         break;
2493
-     }
2494
-
2495
-     if (i >= s->directory.next) {
2496
-        fail = -6;
2497
-        continue;
2498
-     }
2499
-
2500
-     /* make sure there exists an initial mapping */
2501
-     if (mapping && mapping->begin != begin) {
2502
-        mapping->end = begin;
2503
-        mapping = NULL;
2504
-     }
2505
-     if (mapping == NULL) {
2506
-        mapping = insert_mapping(s, begin, begin+1);
2507
-     }
2508
-     /* most members will be fixed in commit_mappings() */
2509
-     assert(commit->path);
2510
-     mapping->path = commit->path;
2511
-     mapping->read_only = 0;
2512
-     mapping->mode = MODE_NORMAL;
2513
-     mapping->info.file.offset = 0;
2514
-
2515
-     if (commit_one_file(s, i, 0))
2516
-        fail = -7;
2517
-
2518
-     break;
2519
-    }
2520
-    default:
2521
+ assert(mapping);
2522
+ assert(mapping->begin == begin);
2523
+ assert(commit->path == NULL);
2524
+
2525
+ if (commit_one_file(s, commit->param.writeout.dir_index,
2526
+ commit->param.writeout.modified_offset))
2527
+ fail = -3;
2528
+
2529
+ break;
2530
+ }
2531
+ case ACTION_NEW_FILE: {
2532
+ int begin = commit->param.new_file.first_cluster;
2533
+ mapping_t* mapping = find_mapping_for_cluster(s, begin);
2534
+ direntry_t* entry;
2535
+ int i;
2536
+
2537
+ /* find direntry */
2538
+ for (i = 0; i < s->directory.next; i++) {
2539
+ entry = array_get(&(s->directory), i);
2540
+ if (is_file(entry) && begin_of_direntry(entry) == begin)
2541
+ break;
2542
+ }
2543
+
2544
+ if (i >= s->directory.next) {
2545
+ fail = -6;
2546
+ continue;
2547
+ }
2548
+
2549
+ /* make sure there exists an initial mapping */
2550
+ if (mapping && mapping->begin != begin) {
2551
+ mapping->end = begin;
2552
+ mapping = NULL;
2553
+ }
2554
+ if (mapping == NULL) {
2555
+ mapping = insert_mapping(s, begin, begin+1);
2556
+ }
2557
+ /* most members will be fixed in commit_mappings() */
2558
+ assert(commit->path);
2559
+ mapping->path = commit->path;
2560
+ mapping->read_only = 0;
2561
+ mapping->mode = MODE_NORMAL;
2562
+ mapping->info.file.offset = 0;
2563
+
2564
+ if (commit_one_file(s, i, 0))
2565
+ fail = -7;
2566
+
2567
+ break;
2568
+ }
2569
+ default:
2570
abort();
2571
-    }
2572
+ }
2573
}
2574
if (i > 0 && array_remove_slice(&(s->commits), 0, i))
2575
-    return -1;
2576
+ return -1;
2577
return fail;
2578
}
2579
2580
@@ -XXX,XX +XXX,XX @@ static int handle_deletes(BDRVVVFATState* s)
2581
/* delete files corresponding to mappings marked as deleted */
2582
/* handle DELETEs and unused mappings (modified_fat_get(s, mapping->begin) == 0) */
2583
while (deferred && deleted) {
2584
-    deferred = 0;
2585
-    deleted = 0;
2586
-
2587
-    for (i = 1; i < s->mapping.next; i++) {
2588
-     mapping_t* mapping = array_get(&(s->mapping), i);
2589
-     if (mapping->mode & MODE_DELETED) {
2590
-        direntry_t* entry = array_get(&(s->directory),
2591
-            mapping->dir_index);
2592
-
2593
-        if (is_free(entry)) {
2594
-         /* remove file/directory */
2595
-         if (mapping->mode & MODE_DIRECTORY) {
2596
-            int j, next_dir_index = s->directory.next,
2597
-            first_dir_index = mapping->info.dir.first_dir_index;
2598
-
2599
-            if (rmdir(mapping->path) < 0) {
2600
-             if (errno == ENOTEMPTY) {
2601
-                deferred++;
2602
-                continue;
2603
-             } else
2604
-                return -5;
2605
-            }
2606
-
2607
-            for (j = 1; j < s->mapping.next; j++) {
2608
-             mapping_t* m = array_get(&(s->mapping), j);
2609
-             if (m->mode & MODE_DIRECTORY &&
2610
-                 m->info.dir.first_dir_index >
2611
-                 first_dir_index &&
2612
-                 m->info.dir.first_dir_index <
2613
-                 next_dir_index)
2614
-                next_dir_index =
2615
-                 m->info.dir.first_dir_index;
2616
-            }
2617
-            remove_direntries(s, first_dir_index,
2618
-                next_dir_index - first_dir_index);
2619
-
2620
-            deleted++;
2621
-         }
2622
-        } else {
2623
-         if (unlink(mapping->path))
2624
-            return -4;
2625
-         deleted++;
2626
-        }
2627
-        DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2628
-        remove_mapping(s, i);
2629
-     }
2630
-    }
2631
+ deferred = 0;
2632
+ deleted = 0;
2633
+
2634
+ for (i = 1; i < s->mapping.next; i++) {
2635
+ mapping_t* mapping = array_get(&(s->mapping), i);
2636
+ if (mapping->mode & MODE_DELETED) {
2637
+ direntry_t* entry = array_get(&(s->directory),
2638
+ mapping->dir_index);
2639
+
2640
+ if (is_free(entry)) {
2641
+ /* remove file/directory */
2642
+ if (mapping->mode & MODE_DIRECTORY) {
2643
+ int j, next_dir_index = s->directory.next,
2644
+ first_dir_index = mapping->info.dir.first_dir_index;
2645
+
2646
+ if (rmdir(mapping->path) < 0) {
2647
+ if (errno == ENOTEMPTY) {
2648
+ deferred++;
2649
+ continue;
2650
+ } else
2651
+ return -5;
2652
+ }
2653
+
2654
+ for (j = 1; j < s->mapping.next; j++) {
2655
+ mapping_t* m = array_get(&(s->mapping), j);
2656
+ if (m->mode & MODE_DIRECTORY &&
2657
+ m->info.dir.first_dir_index >
2658
+ first_dir_index &&
2659
+ m->info.dir.first_dir_index <
2660
+ next_dir_index)
2661
+ next_dir_index =
2662
+ m->info.dir.first_dir_index;
2663
+ }
2664
+ remove_direntries(s, first_dir_index,
2665
+ next_dir_index - first_dir_index);
2666
+
2667
+ deleted++;
2668
+ }
2669
+ } else {
2670
+ if (unlink(mapping->path))
2671
+ return -4;
2672
+ deleted++;
2673
+ }
2674
+ DLOG(fprintf(stderr, "DELETE (%d)\n", i); print_mapping(mapping); print_direntry(entry));
2675
+ remove_mapping(s, i);
2676
+ }
2677
+ }
2678
}
2679
2680
return 0;
2681
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
2682
2683
/* the real meat are the commits. Nothing to do? Move along! */
2684
if (s->commits.next == 0)
2685
-    return 0;
2686
+ return 0;
2687
2688
vvfat_close_current_file(s);
2689
2690
ret = handle_renames_and_mkdirs(s);
2691
if (ret) {
2692
-    fprintf(stderr, "Error handling renames (%d)\n", ret);
2693
+ fprintf(stderr, "Error handling renames (%d)\n", ret);
2694
abort();
2695
-    return ret;
2696
+ return ret;
2697
}
2698
2699
/* copy FAT (with bdrv_read) */
2700
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
2701
/* recurse direntries from root (using bs->bdrv_read) */
2702
ret = commit_direntries(s, 0, -1);
2703
if (ret) {
2704
-    fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2705
+ fprintf(stderr, "Fatal: error while committing (%d)\n", ret);
2706
abort();
2707
-    return ret;
2708
+ return ret;
2709
}
2710
2711
ret = handle_commits(s);
2712
if (ret) {
2713
-    fprintf(stderr, "Error handling commits (%d)\n", ret);
2714
+ fprintf(stderr, "Error handling commits (%d)\n", ret);
2715
abort();
2716
-    return ret;
2717
+ return ret;
2718
}
2719
2720
ret = handle_deletes(s);
2721
if (ret) {
2722
-    fprintf(stderr, "Error deleting\n");
2723
+ fprintf(stderr, "Error deleting\n");
2724
abort();
2725
-    return ret;
2726
+ return ret;
2727
}
2728
2729
if (s->qcow->bs->drv->bdrv_make_empty) {
2730
@@ -XXX,XX +XXX,XX @@ static int try_commit(BDRVVVFATState* s)
2731
vvfat_close_current_file(s);
2732
DLOG(checkpoint());
2733
if(!is_consistent(s))
2734
-    return -1;
2735
+ return -1;
2736
return do_commit(s);
2737
}
2738
2739
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
2740
*/
2741
2742
if (sector_num < s->first_sectors_number)
2743
-    return -1;
2744
+ return -1;
2745
2746
for (i = sector2cluster(s, sector_num);
2747
-     i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2748
-    mapping_t* mapping = find_mapping_for_cluster(s, i);
2749
-    if (mapping) {
2750
-     if (mapping->read_only) {
2751
-        fprintf(stderr, "Tried to write to write-protected file %s\n",
2752
-            mapping->path);
2753
-        return -1;
2754
-     }
2755
-
2756
-     if (mapping->mode & MODE_DIRECTORY) {
2757
-        int begin = cluster2sector(s, i);
2758
-        int end = begin + s->sectors_per_cluster, k;
2759
-        int dir_index;
2760
-        const direntry_t* direntries;
2761
-        long_file_name lfn;
2762
-
2763
-        lfn_init(&lfn);
2764
-
2765
-        if (begin < sector_num)
2766
-         begin = sector_num;
2767
-        if (end > sector_num + nb_sectors)
2768
-         end = sector_num + nb_sectors;
2769
-        dir_index = mapping->dir_index +
2770
-         0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2771
-        direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2772
-
2773
-        for (k = 0; k < (end - begin) * 0x10; k++) {
2774
-         /* do not allow non-ASCII filenames */
2775
-         if (parse_long_name(&lfn, direntries + k) < 0) {
2776
-            fprintf(stderr, "Warning: non-ASCII filename\n");
2777
-            return -1;
2778
-         }
2779
-         /* no access to the direntry of a read-only file */
2780
-         else if (is_short_name(direntries+k) &&
2781
-             (direntries[k].attributes & 1)) {
2782
-            if (memcmp(direntries + k,
2783
-                 array_get(&(s->directory), dir_index + k),
2784
-                 sizeof(direntry_t))) {
2785
-             fprintf(stderr, "Warning: tried to write to write-protected file\n");
2786
-             return -1;
2787
-            }
2788
-         }
2789
-        }
2790
-     }
2791
-     i = mapping->end;
2792
-    } else
2793
-     i++;
2794
+ i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
2795
+ mapping_t* mapping = find_mapping_for_cluster(s, i);
2796
+ if (mapping) {
2797
+ if (mapping->read_only) {
2798
+ fprintf(stderr, "Tried to write to write-protected file %s\n",
2799
+ mapping->path);
2800
+ return -1;
2801
+ }
2802
+
2803
+ if (mapping->mode & MODE_DIRECTORY) {
2804
+ int begin = cluster2sector(s, i);
2805
+ int end = begin + s->sectors_per_cluster, k;
2806
+ int dir_index;
2807
+ const direntry_t* direntries;
2808
+ long_file_name lfn;
2809
+
2810
+ lfn_init(&lfn);
2811
+
2812
+ if (begin < sector_num)
2813
+ begin = sector_num;
2814
+ if (end > sector_num + nb_sectors)
2815
+ end = sector_num + nb_sectors;
2816
+ dir_index = mapping->dir_index +
2817
+ 0x10 * (begin - mapping->begin * s->sectors_per_cluster);
2818
+ direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
2819
+
2820
+ for (k = 0; k < (end - begin) * 0x10; k++) {
2821
+ /* do not allow non-ASCII filenames */
2822
+ if (parse_long_name(&lfn, direntries + k) < 0) {
2823
+ fprintf(stderr, "Warning: non-ASCII filename\n");
2824
+ return -1;
2825
+ }
2826
+ /* no access to the direntry of a read-only file */
2827
+ else if (is_short_name(direntries+k) &&
2828
+ (direntries[k].attributes & 1)) {
2829
+ if (memcmp(direntries + k,
2830
+ array_get(&(s->directory), dir_index + k),
2831
+ sizeof(direntry_t))) {
2832
+ fprintf(stderr, "Warning: tried to write to write-protected file\n");
2833
+ return -1;
2834
+ }
2835
+ }
2836
+ }
2837
+ }
2838
+ i = mapping->end;
2839
+ } else
2840
+ i++;
2841
}
2842
2843
/*
2844
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
2845
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
2846
ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
2847
if (ret < 0) {
2848
-    fprintf(stderr, "Error writing to qcow backend\n");
2849
-    return ret;
2850
+ fprintf(stderr, "Error writing to qcow backend\n");
2851
+ return ret;
2852
}
2853
2854
for (i = sector2cluster(s, sector_num);
2855
-     i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2856
-    if (i >= 0)
2857
-     s->used_clusters[i] |= USED_ALLOCATED;
2858
+ i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
2859
+ if (i >= 0)
2860
+ s->used_clusters[i] |= USED_ALLOCATED;
2861
2862
DLOG(checkpoint());
2863
/* TODO: add timeout */
2864
@@ -XXX,XX +XXX,XX @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
2865
}
2866
2867
static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
2868
-    int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
2869
+ int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
2870
{
2871
*n = bs->total_sectors - sector_num;
2872
if (*n > nb_sectors) {
2873
@@ -XXX,XX +XXX,XX @@ static void checkpoint(void) {
2874
assert(!vvv->current_mapping || vvv->current_fd || (vvv->current_mapping->mode & MODE_DIRECTORY));
2875
#if 0
2876
if (((direntry_t*)vvv->directory.pointer)[1].attributes != 0xf)
2877
-    fprintf(stderr, "Nonono!\n");
2878
+ fprintf(stderr, "Nonono!\n");
2879
mapping_t* mapping;
2880
direntry_t* direntry;
2881
assert(vvv->mapping.size >= vvv->mapping.item_size * vvv->mapping.next);
2882
assert(vvv->directory.size >= vvv->directory.item_size * vvv->directory.next);
2883
if (vvv->mapping.next<47)
2884
-    return;
2885
+ return;
2886
assert((mapping = array_get(&(vvv->mapping), 47)));
2887
assert(mapping->dir_index < vvv->directory.next);
2888
direntry = array_get(&(vvv->directory), mapping->dir_index);
2889
--
120
--
2890
1.8.3.1
121
2.37.3
2891
2892
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Upcoming patches are going to switch to byte-based interfaces
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
instead of sector-based. Even worse, trace_backup_do_cow_enter()
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
had a weird mix of cluster and sector indices.
5
functions where this holds.
6
6
7
The trace interface is low enough that there are no stability
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
guarantees, and therefore nothing wrong with changing our units,
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
even in cases like trace_backup_do_cow_skip() where we are not
9
Message-Id: <20220922084924.201610-20-pbonzini@redhat.com>
10
changing the trace output. So make the tracing uniformly use
11
bytes.
12
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: John Snow <jsnow@redhat.com>
15
Reviewed-by: Jeff Cody <jcody@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
12
---
19
block/backup.c | 16 ++++++++++------
13
block/throttle.c | 2 +-
20
block/commit.c | 3 ++-
14
1 file changed, 1 insertion(+), 1 deletion(-)
21
block/mirror.c | 26 +++++++++++++++++---------
22
block/stream.c | 3 ++-
23
block/trace-events | 14 +++++++-------
24
5 files changed, 38 insertions(+), 24 deletions(-)
25
15
26
diff --git a/block/backup.c b/block/backup.c
16
diff --git a/block/throttle.c b/block/throttle.c
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/block/backup.c
18
--- a/block/throttle.c
29
+++ b/block/backup.c
19
+++ b/block/throttle.c
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
20
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs,
31
void *bounce_buffer = NULL;
21
BDRV_REQ_WRITE_COMPRESSED);
32
int ret = 0;
22
}
33
int64_t sectors_per_cluster = cluster_size_sectors(job);
23
34
+ int64_t bytes_per_cluster = sectors_per_cluster * BDRV_SECTOR_SIZE;
24
-static int throttle_co_flush(BlockDriverState *bs)
35
int64_t start, end;
25
+static int coroutine_fn throttle_co_flush(BlockDriverState *bs)
36
int n;
26
{
37
27
return bdrv_co_flush(bs->file->bs);
38
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
28
}
39
start = sector_num / sectors_per_cluster;
40
end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
41
42
- trace_backup_do_cow_enter(job, start, sector_num, nb_sectors);
43
+ trace_backup_do_cow_enter(job, start * bytes_per_cluster,
44
+ sector_num * BDRV_SECTOR_SIZE,
45
+ nb_sectors * BDRV_SECTOR_SIZE);
46
47
wait_for_overlapping_requests(job, start, end);
48
cow_request_begin(&cow_request, job, start, end);
49
50
for (; start < end; start++) {
51
if (test_bit(start, job->done_bitmap)) {
52
- trace_backup_do_cow_skip(job, start);
53
+ trace_backup_do_cow_skip(job, start * bytes_per_cluster);
54
continue; /* already copied */
55
}
56
57
- trace_backup_do_cow_process(job, start);
58
+ trace_backup_do_cow_process(job, start * bytes_per_cluster);
59
60
n = MIN(sectors_per_cluster,
61
job->common.len / BDRV_SECTOR_SIZE -
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
63
bounce_qiov.size, &bounce_qiov,
64
is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
65
if (ret < 0) {
66
- trace_backup_do_cow_read_fail(job, start, ret);
67
+ trace_backup_do_cow_read_fail(job, start * bytes_per_cluster, ret);
68
if (error_is_read) {
69
*error_is_read = true;
70
}
71
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
72
job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
73
}
74
if (ret < 0) {
75
- trace_backup_do_cow_write_fail(job, start, ret);
76
+ trace_backup_do_cow_write_fail(job, start * bytes_per_cluster, ret);
77
if (error_is_read) {
78
*error_is_read = false;
79
}
80
@@ -XXX,XX +XXX,XX @@ out:
81
82
cow_request_end(&cow_request);
83
84
- trace_backup_do_cow_return(job, sector_num, nb_sectors, ret);
85
+ trace_backup_do_cow_return(job, sector_num * BDRV_SECTOR_SIZE,
86
+ nb_sectors * BDRV_SECTOR_SIZE, ret);
87
88
qemu_co_rwlock_unlock(&job->flush_rwlock);
89
90
diff --git a/block/commit.c b/block/commit.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/block/commit.c
93
+++ b/block/commit.c
94
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
95
COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
96
&n);
97
copy = (ret == 1);
98
- trace_commit_one_iteration(s, sector_num, n, ret);
99
+ trace_commit_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
100
+ n * BDRV_SECTOR_SIZE, ret);
101
if (copy) {
102
ret = commit_populate(s->top, s->base, sector_num, n, buf);
103
bytes_written += n * BDRV_SECTOR_SIZE;
104
diff --git a/block/mirror.c b/block/mirror.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/block/mirror.c
107
+++ b/block/mirror.c
108
@@ -XXX,XX +XXX,XX @@ static void mirror_iteration_done(MirrorOp *op, int ret)
109
int64_t chunk_num;
110
int i, nb_chunks, sectors_per_chunk;
111
112
- trace_mirror_iteration_done(s, op->sector_num, op->nb_sectors, ret);
113
+ trace_mirror_iteration_done(s, op->sector_num * BDRV_SECTOR_SIZE,
114
+ op->nb_sectors * BDRV_SECTOR_SIZE, ret);
115
116
s->in_flight--;
117
s->sectors_in_flight -= op->nb_sectors;
118
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
119
nb_chunks = DIV_ROUND_UP(nb_sectors, sectors_per_chunk);
120
121
while (s->buf_free_count < nb_chunks) {
122
- trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
123
+ trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
124
+ s->in_flight);
125
mirror_wait_for_io(s);
126
}
127
128
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
129
/* Copy the dirty cluster. */
130
s->in_flight++;
131
s->sectors_in_flight += nb_sectors;
132
- trace_mirror_one_iteration(s, sector_num, nb_sectors);
133
+ trace_mirror_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
134
+ nb_sectors * BDRV_SECTOR_SIZE);
135
136
blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov, 0,
137
mirror_read_complete, op);
138
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
139
if (sector_num < 0) {
140
bdrv_set_dirty_iter(s->dbi, 0);
141
sector_num = bdrv_dirty_iter_next(s->dbi);
142
- trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap));
143
+ trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap) *
144
+ BDRV_SECTOR_SIZE);
145
assert(sector_num >= 0);
146
}
147
bdrv_dirty_bitmap_unlock(s->dirty_bitmap);
148
149
first_chunk = sector_num / sectors_per_chunk;
150
while (test_bit(first_chunk, s->in_flight_bitmap)) {
151
- trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
152
+ trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
153
+ s->in_flight);
154
mirror_wait_for_io(s);
155
}
156
157
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
158
}
159
160
while (s->in_flight >= MAX_IN_FLIGHT) {
161
- trace_mirror_yield_in_flight(s, sector_num, s->in_flight);
162
+ trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
163
+ s->in_flight);
164
mirror_wait_for_io(s);
165
}
166
167
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
168
s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
169
if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
170
(cnt == 0 && s->in_flight > 0)) {
171
- trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight);
172
+ trace_mirror_yield(s, cnt * BDRV_SECTOR_SIZE,
173
+ s->buf_free_count, s->in_flight);
174
mirror_wait_for_io(s);
175
continue;
176
} else if (cnt != 0) {
177
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
178
* whether to switch to target check one last time if I/O has
179
* come in the meanwhile, and if not flush the data to disk.
180
*/
181
- trace_mirror_before_drain(s, cnt);
182
+ trace_mirror_before_drain(s, cnt * BDRV_SECTOR_SIZE);
183
184
bdrv_drained_begin(bs);
185
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
186
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
187
}
188
189
ret = 0;
190
- trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
191
+ trace_mirror_before_sleep(s, cnt * BDRV_SECTOR_SIZE,
192
+ s->synced, delay_ns);
193
if (!s->synced) {
194
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
195
if (block_job_is_cancelled(&s->common)) {
196
diff --git a/block/stream.c b/block/stream.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/block/stream.c
199
+++ b/block/stream.c
200
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
201
202
copy = (ret == 1);
203
}
204
- trace_stream_one_iteration(s, sector_num, n, ret);
205
+ trace_stream_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
206
+ n * BDRV_SECTOR_SIZE, ret);
207
if (copy) {
208
ret = stream_populate(blk, sector_num, n, buf);
209
}
210
diff --git a/block/trace-events b/block/trace-events
211
index XXXXXXX..XXXXXXX 100644
212
--- a/block/trace-events
213
+++ b/block/trace-events
214
@@ -XXX,XX +XXX,XX @@ bdrv_co_pwrite_zeroes(void *bs, int64_t offset, int count, int flags) "bs %p off
215
bdrv_co_do_copy_on_readv(void *bs, int64_t offset, unsigned int bytes, int64_t cluster_offset, unsigned int cluster_bytes) "bs %p offset %"PRId64" bytes %u cluster_offset %"PRId64" cluster_bytes %u"
216
217
# block/stream.c
218
-stream_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d"
219
+stream_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
220
stream_start(void *bs, void *base, void *s) "bs %p base %p s %p"
221
222
# block/commit.c
223
-commit_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocated) "s %p sector_num %"PRId64" nb_sectors %d is_allocated %d"
224
+commit_one_iteration(void *s, int64_t offset, uint64_t bytes, int is_allocated) "s %p offset %" PRId64 " bytes %" PRIu64 " is_allocated %d"
225
commit_start(void *bs, void *base, void *top, void *s) "bs %p base %p top %p s %p"
226
227
# block/mirror.c
228
@@ -XXX,XX +XXX,XX @@ mirror_restart_iter(void *s, int64_t cnt) "s %p dirty count %"PRId64
229
mirror_before_flush(void *s) "s %p"
230
mirror_before_drain(void *s, int64_t cnt) "s %p dirty count %"PRId64
231
mirror_before_sleep(void *s, int64_t cnt, int synced, uint64_t delay_ns) "s %p dirty count %"PRId64" synced %d delay %"PRIu64"ns"
232
-mirror_one_iteration(void *s, int64_t sector_num, int nb_sectors) "s %p sector_num %"PRId64" nb_sectors %d"
233
-mirror_iteration_done(void *s, int64_t sector_num, int nb_sectors, int ret) "s %p sector_num %"PRId64" nb_sectors %d ret %d"
234
+mirror_one_iteration(void *s, int64_t offset, uint64_t bytes) "s %p offset %" PRId64 " bytes %" PRIu64
235
+mirror_iteration_done(void *s, int64_t offset, uint64_t bytes, int ret) "s %p offset %" PRId64 " bytes %" PRIu64 " ret %d"
236
mirror_yield(void *s, int64_t cnt, int buf_free_count, int in_flight) "s %p dirty count %"PRId64" free buffers %d in_flight %d"
237
-mirror_yield_in_flight(void *s, int64_t sector_num, int in_flight) "s %p sector_num %"PRId64" in_flight %d"
238
+mirror_yield_in_flight(void *s, int64_t offset, int in_flight) "s %p offset %" PRId64 " in_flight %d"
239
240
# block/backup.c
241
-backup_do_cow_enter(void *job, int64_t start, int64_t sector_num, int nb_sectors) "job %p start %"PRId64" sector_num %"PRId64" nb_sectors %d"
242
-backup_do_cow_return(void *job, int64_t sector_num, int nb_sectors, int ret) "job %p sector_num %"PRId64" nb_sectors %d ret %d"
243
+backup_do_cow_enter(void *job, int64_t start, int64_t offset, uint64_t bytes) "job %p start %" PRId64 " offset %" PRId64 " bytes %" PRIu64
244
+backup_do_cow_return(void *job, int64_t offset, uint64_t bytes, int ret) "job %p offset %" PRId64 " bytes %" PRIu64 " ret %d"
245
backup_do_cow_skip(void *job, int64_t start) "job %p start %"PRId64
246
backup_do_cow_process(void *job, int64_t start) "job %p start %"PRId64
247
backup_do_cow_read_fail(void *job, int64_t start, int ret) "job %p start %"PRId64" ret %d"
248
--
29
--
249
1.8.3.1
30
2.37.3
250
251
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Auto loading bitmaps are bitmaps in Qcow2, with the AUTO flag set. They
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
are loaded when the image is opened and become BdrvDirtyBitmaps for the
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
corresponding drive.
5
functions where this holds.
6
6
7
Extra data in bitmaps is not supported for now.
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20220922084924.201610-21-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/vmdk.c | 22 ++++++++++++----------
15
1 file changed, 12 insertions(+), 10 deletions(-)
8
16
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
diff --git a/block/vmdk.c b/block/vmdk.c
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Message-id: 20170628120530.31251-12-vsementsov@virtuozzo.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/qcow2-bitmap.c | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++
16
block/qcow2.c | 17 ++-
17
block/qcow2.h | 2 +
18
3 files changed, 406 insertions(+), 2 deletions(-)
19
20
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2-bitmap.c
19
--- a/block/vmdk.c
23
+++ b/block/qcow2-bitmap.c
20
+++ b/block/vmdk.c
24
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs,
25
26
/* Bitmap directory entry flags */
27
#define BME_RESERVED_FLAGS 0xfffffffcU
28
+#define BME_FLAG_IN_USE (1U << 0)
29
+#define BME_FLAG_AUTO (1U << 1)
30
31
/* bits [1, 8] U [56, 63] are reserved */
32
#define BME_TABLE_ENTRY_RESERVED_MASK 0xff000000000001feULL
33
@@ -XXX,XX +XXX,XX @@ typedef enum BitmapType {
34
BT_DIRTY_TRACKING_BITMAP = 1
35
} BitmapType;
36
37
+static inline bool can_write(BlockDriverState *bs)
38
+{
39
+ return !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
40
+}
41
+
42
+static int update_header_sync(BlockDriverState *bs)
43
+{
44
+ int ret;
45
+
46
+ ret = qcow2_update_header(bs);
47
+ if (ret < 0) {
48
+ return ret;
49
+ }
50
+
51
+ return bdrv_flush(bs);
52
+}
53
+
54
static int check_table_entry(uint64_t entry, int cluster_size)
55
{
56
uint64_t offset;
57
@@ -XXX,XX +XXX,XX @@ fail:
58
return ret;
22
return ret;
59
}
23
}
60
24
61
+/* This function returns the number of disk sectors covered by a single qcow2
25
-static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
62
+ * cluster of bitmap data. */
26
- int64_t offset_in_cluster, QEMUIOVector *qiov,
63
+static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
27
- uint64_t qiov_offset, uint64_t n_bytes,
64
+ const BdrvDirtyBitmap *bitmap)
28
- uint64_t offset)
65
+{
29
+static int coroutine_fn
66
+ uint32_t sector_granularity =
30
+vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
67
+ bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
31
+ int64_t offset_in_cluster, QEMUIOVector *qiov,
68
+
32
+ uint64_t qiov_offset, uint64_t n_bytes,
69
+ return (uint64_t)sector_granularity * (s->cluster_size << 3);
33
+ uint64_t offset)
70
+}
71
+
72
+/* load_bitmap_data
73
+ * @bitmap_table entries must satisfy specification constraints.
74
+ * @bitmap must be cleared */
75
+static int load_bitmap_data(BlockDriverState *bs,
76
+ const uint64_t *bitmap_table,
77
+ uint32_t bitmap_table_size,
78
+ BdrvDirtyBitmap *bitmap)
79
+{
80
+ int ret = 0;
81
+ BDRVQcow2State *s = bs->opaque;
82
+ uint64_t sector, sbc;
83
+ uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
84
+ uint8_t *buf = NULL;
85
+ uint64_t i, tab_size =
86
+ size_to_clusters(s,
87
+ bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
88
+
89
+ if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) {
90
+ return -EINVAL;
91
+ }
92
+
93
+ buf = g_malloc(s->cluster_size);
94
+ sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
95
+ for (i = 0, sector = 0; i < tab_size; ++i, sector += sbc) {
96
+ uint64_t count = MIN(bm_size - sector, sbc);
97
+ uint64_t entry = bitmap_table[i];
98
+ uint64_t offset = entry & BME_TABLE_ENTRY_OFFSET_MASK;
99
+
100
+ assert(check_table_entry(entry, s->cluster_size) == 0);
101
+
102
+ if (offset == 0) {
103
+ if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) {
104
+ bdrv_dirty_bitmap_deserialize_ones(bitmap, sector, count,
105
+ false);
106
+ } else {
107
+ /* No need to deserialize zeros because the dirty bitmap is
108
+ * already cleared */
109
+ }
110
+ } else {
111
+ ret = bdrv_pread(bs->file, offset, buf, s->cluster_size);
112
+ if (ret < 0) {
113
+ goto finish;
114
+ }
115
+ bdrv_dirty_bitmap_deserialize_part(bitmap, buf, sector, count,
116
+ false);
117
+ }
118
+ }
119
+ ret = 0;
120
+
121
+ bdrv_dirty_bitmap_deserialize_finish(bitmap);
122
+
123
+finish:
124
+ g_free(buf);
125
+
126
+ return ret;
127
+}
128
+
129
+static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
130
+ Qcow2Bitmap *bm, Error **errp)
131
+{
132
+ int ret;
133
+ uint64_t *bitmap_table = NULL;
134
+ uint32_t granularity;
135
+ BdrvDirtyBitmap *bitmap = NULL;
136
+
137
+ if (bm->flags & BME_FLAG_IN_USE) {
138
+ error_setg(errp, "Bitmap '%s' is in use", bm->name);
139
+ goto fail;
140
+ }
141
+
142
+ ret = bitmap_table_load(bs, &bm->table, &bitmap_table);
143
+ if (ret < 0) {
144
+ error_setg_errno(errp, -ret,
145
+ "Could not read bitmap_table table from image for "
146
+ "bitmap '%s'", bm->name);
147
+ goto fail;
148
+ }
149
+
150
+ granularity = 1U << bm->granularity_bits;
151
+ bitmap = bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp);
152
+ if (bitmap == NULL) {
153
+ goto fail;
154
+ }
155
+
156
+ ret = load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap);
157
+ if (ret < 0) {
158
+ error_setg_errno(errp, -ret, "Could not read bitmap '%s' from image",
159
+ bm->name);
160
+ goto fail;
161
+ }
162
+
163
+ g_free(bitmap_table);
164
+ return bitmap;
165
+
166
+fail:
167
+ g_free(bitmap_table);
168
+ if (bitmap != NULL) {
169
+ bdrv_release_dirty_bitmap(bs, bitmap);
170
+ }
171
+
172
+ return NULL;
173
+}
174
+
175
/*
176
* Bitmap List
177
*/
178
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
179
be32_to_cpus(&entry->extra_data_size);
180
}
181
182
+static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
183
+{
184
+ cpu_to_be64s(&entry->bitmap_table_offset);
185
+ cpu_to_be32s(&entry->bitmap_table_size);
186
+ cpu_to_be32s(&entry->flags);
187
+ cpu_to_be16s(&entry->name_size);
188
+ cpu_to_be32s(&entry->extra_data_size);
189
+}
190
+
191
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
192
{
34
{
193
return align_offset(sizeof(Qcow2BitmapDirEntry) +
35
int ret;
194
@@ -XXX,XX +XXX,XX @@ static int check_dir_entry(BlockDriverState *bs, Qcow2BitmapDirEntry *entry)
36
VmdkGrainMarker *data = NULL;
195
return fail ? -EINVAL : 0;
37
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
196
}
197
198
+static inline void bitmap_directory_to_be(uint8_t *dir, size_t size)
199
+{
200
+ uint8_t *end = dir + size;
201
+ while (dir < end) {
202
+ Qcow2BitmapDirEntry *e = (Qcow2BitmapDirEntry *)dir;
203
+ dir += dir_entry_size(e);
204
+
205
+ bitmap_dir_entry_to_be(e);
206
+ }
207
+}
208
+
209
/*
210
* Bitmap List public functions
211
*/
212
@@ -XXX,XX +XXX,XX @@ static Qcow2BitmapList *bitmap_list_new(void)
213
return bm_list;
214
}
215
216
+static uint32_t bitmap_list_count(Qcow2BitmapList *bm_list)
217
+{
218
+ Qcow2Bitmap *bm;
219
+ uint32_t nb_bitmaps = 0;
220
+
221
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
222
+ nb_bitmaps++;
223
+ }
224
+
225
+ return nb_bitmaps;
226
+}
227
+
228
/* bitmap_list_load
229
* Get bitmap list from qcow2 image. Actually reads bitmap directory,
230
* checks it and convert to bitmap list.
231
@@ -XXX,XX +XXX,XX @@ out:
232
233
return ret;
38
return ret;
234
}
39
}
235
+
40
236
+/* bitmap_list_store
41
-static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
237
+ * Store bitmap list to qcow2 image as a bitmap directory.
42
- int64_t offset_in_cluster, QEMUIOVector *qiov,
238
+ * Everything is checked.
43
- int bytes)
239
+ */
44
+static int coroutine_fn
240
+static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
45
+vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
241
+ uint64_t *offset, uint64_t *size, bool in_place)
46
+ int64_t offset_in_cluster, QEMUIOVector *qiov,
242
+{
47
+ int bytes)
243
+ int ret;
48
{
244
+ uint8_t *dir;
49
int ret;
245
+ int64_t dir_offset = 0;
50
int cluster_bytes, buf_bytes;
246
+ uint64_t dir_size = 0;
51
@@ -XXX,XX +XXX,XX @@ fail:
247
+ Qcow2Bitmap *bm;
52
*
248
+ Qcow2BitmapDirEntry *e;
53
* Returns: error code with 0 for success.
249
+
54
*/
250
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
55
-static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
251
+ dir_size += calc_dir_entry_size(strlen(bm->name), 0);
56
- uint64_t bytes, QEMUIOVector *qiov,
252
+ }
57
- bool zeroed, bool zero_dry_run)
253
+
58
+static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset,
254
+ if (dir_size == 0 || dir_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
59
+ uint64_t bytes, QEMUIOVector *qiov,
255
+ return -EINVAL;
60
+ bool zeroed, bool zero_dry_run)
256
+ }
61
{
257
+
62
BDRVVmdkState *s = bs->opaque;
258
+ if (in_place) {
63
VmdkExtent *extent = NULL;
259
+ if (*size != dir_size || *offset == 0) {
260
+ return -EINVAL;
261
+ }
262
+
263
+ dir_offset = *offset;
264
+ }
265
+
266
+ dir = g_try_malloc(dir_size);
267
+ if (dir == NULL) {
268
+ return -ENOMEM;
269
+ }
270
+
271
+ e = (Qcow2BitmapDirEntry *)dir;
272
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
273
+ e->bitmap_table_offset = bm->table.offset;
274
+ e->bitmap_table_size = bm->table.size;
275
+ e->flags = bm->flags;
276
+ e->type = BT_DIRTY_TRACKING_BITMAP;
277
+ e->granularity_bits = bm->granularity_bits;
278
+ e->name_size = strlen(bm->name);
279
+ e->extra_data_size = 0;
280
+ memcpy(e + 1, bm->name, e->name_size);
281
+
282
+ if (check_dir_entry(bs, e) < 0) {
283
+ ret = -EINVAL;
284
+ goto fail;
285
+ }
286
+
287
+ e = next_dir_entry(e);
288
+ }
289
+
290
+ bitmap_directory_to_be(dir, dir_size);
291
+
292
+ if (!in_place) {
293
+ dir_offset = qcow2_alloc_clusters(bs, dir_size);
294
+ if (dir_offset < 0) {
295
+ ret = dir_offset;
296
+ goto fail;
297
+ }
298
+ }
299
+
300
+ ret = qcow2_pre_write_overlap_check(bs, 0, dir_offset, dir_size);
301
+ if (ret < 0) {
302
+ goto fail;
303
+ }
304
+
305
+ ret = bdrv_pwrite(bs->file, dir_offset, dir, dir_size);
306
+ if (ret < 0) {
307
+ goto fail;
308
+ }
309
+
310
+ g_free(dir);
311
+
312
+ if (!in_place) {
313
+ *size = dir_size;
314
+ *offset = dir_offset;
315
+ }
316
+
317
+ return 0;
318
+
319
+fail:
320
+ g_free(dir);
321
+
322
+ if (!in_place && dir_offset > 0) {
323
+ qcow2_free_clusters(bs, dir_offset, dir_size, QCOW2_DISCARD_OTHER);
324
+ }
325
+
326
+ return ret;
327
+}
328
+
329
+/*
330
+ * Bitmap List end
331
+ */
332
+
333
+static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
334
+ Qcow2BitmapList *bm_list)
335
+{
336
+ BDRVQcow2State *s = bs->opaque;
337
+ int ret;
338
+
339
+ if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS) ||
340
+ bm_list == NULL || QSIMPLEQ_EMPTY(bm_list) ||
341
+ bitmap_list_count(bm_list) != s->nb_bitmaps)
342
+ {
343
+ return -EINVAL;
344
+ }
345
+
346
+ s->autoclear_features &= ~(uint64_t)QCOW2_AUTOCLEAR_BITMAPS;
347
+ ret = update_header_sync(bs);
348
+ if (ret < 0) {
349
+ /* Two variants are possible here:
350
+ * 1. Autoclear flag is dropped, all bitmaps will be lost.
351
+ * 2. Autoclear flag is not dropped, old state is left.
352
+ */
353
+ return ret;
354
+ }
355
+
356
+ /* autoclear bit is not set, so we can safely update bitmap directory */
357
+
358
+ ret = bitmap_list_store(bs, bm_list, &s->bitmap_directory_offset,
359
+ &s->bitmap_directory_size, true);
360
+ if (ret < 0) {
361
+ /* autoclear bit is cleared, so all leaked clusters would be removed on
362
+ * qemu-img check */
363
+ return ret;
364
+ }
365
+
366
+ ret = update_header_sync(bs);
367
+ if (ret < 0) {
368
+ /* autoclear bit is cleared, so all leaked clusters would be removed on
369
+ * qemu-img check */
370
+ return ret;
371
+ }
372
+
373
+ s->autoclear_features |= QCOW2_AUTOCLEAR_BITMAPS;
374
+ return update_header_sync(bs);
375
+ /* If final update_header_sync() fails, two variants are possible:
376
+ * 1. Autoclear flag is not set, all bitmaps will be lost.
377
+ * 2. Autoclear flag is set, header and directory are successfully updated.
378
+ */
379
+}
380
+
381
+/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */
382
+static void release_dirty_bitmap_helper(gpointer bitmap,
383
+ gpointer bs)
384
+{
385
+ bdrv_release_dirty_bitmap(bs, bitmap);
386
+}
387
+
388
+/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */
389
+static void set_readonly_helper(gpointer bitmap, gpointer value)
390
+{
391
+ bdrv_dirty_bitmap_set_readonly(bitmap, (bool)value);
392
+}
393
+
394
+/* qcow2_load_autoloading_dirty_bitmaps()
395
+ * Return value is a hint for caller: true means that the Qcow2 header was
396
+ * updated. (false doesn't mean that the header should be updated by the
397
+ * caller, it just means that updating was not needed or the image cannot be
398
+ * written to).
399
+ * On failure the function returns false.
400
+ */
401
+bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
402
+{
403
+ BDRVQcow2State *s = bs->opaque;
404
+ Qcow2BitmapList *bm_list;
405
+ Qcow2Bitmap *bm;
406
+ GSList *created_dirty_bitmaps = NULL;
407
+ bool header_updated = false;
408
+
409
+ if (s->nb_bitmaps == 0) {
410
+ /* No bitmaps - nothing to do */
411
+ return false;
412
+ }
413
+
414
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
415
+ s->bitmap_directory_size, errp);
416
+ if (bm_list == NULL) {
417
+ return false;
418
+ }
419
+
420
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
421
+ if ((bm->flags & BME_FLAG_AUTO) && !(bm->flags & BME_FLAG_IN_USE)) {
422
+ BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
423
+ if (bitmap == NULL) {
424
+ goto fail;
425
+ }
426
+ bm->flags |= BME_FLAG_IN_USE;
427
+ created_dirty_bitmaps =
428
+ g_slist_append(created_dirty_bitmaps, bitmap);
429
+ }
430
+ }
431
+
432
+ if (created_dirty_bitmaps != NULL) {
433
+ if (can_write(bs)) {
434
+ /* in_use flags must be updated */
435
+ int ret = update_ext_header_and_dir_in_place(bs, bm_list);
436
+ if (ret < 0) {
437
+ error_setg_errno(errp, -ret, "Can't update bitmap directory");
438
+ goto fail;
439
+ }
440
+ header_updated = true;
441
+ } else {
442
+ g_slist_foreach(created_dirty_bitmaps, set_readonly_helper,
443
+ (gpointer)true);
444
+ }
445
+ }
446
+
447
+ g_slist_free(created_dirty_bitmaps);
448
+ bitmap_list_free(bm_list);
449
+
450
+ return header_updated;
451
+
452
+fail:
453
+ g_slist_foreach(created_dirty_bitmaps, release_dirty_bitmap_helper, bs);
454
+ g_slist_free(created_dirty_bitmaps);
455
+ bitmap_list_free(bm_list);
456
+
457
+ return false;
458
+}
459
diff --git a/block/qcow2.c b/block/qcow2.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/block/qcow2.c
462
+++ b/block/qcow2.c
463
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
464
465
/* Clear unknown autoclear feature bits */
466
update_header |= s->autoclear_features & ~QCOW2_AUTOCLEAR_MASK;
467
-
468
- if (update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE)) {
469
+ update_header =
470
+ update_header && !bs->read_only && !(flags & BDRV_O_INACTIVE);
471
+ if (update_header) {
472
s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
473
+ }
474
+
475
+ if (qcow2_load_autoloading_dirty_bitmaps(bs, &local_err)) {
476
+ update_header = false;
477
+ }
478
+ if (local_err != NULL) {
479
+ error_propagate(errp, local_err);
480
+ ret = -EINVAL;
481
+ goto fail;
482
+ }
483
+
484
+ if (update_header) {
485
ret = qcow2_update_header(bs);
486
if (ret < 0) {
487
error_setg_errno(errp, -ret, "Could not update qcow2 header");
488
diff --git a/block/qcow2.h b/block/qcow2.h
489
index XXXXXXX..XXXXXXX 100644
490
--- a/block/qcow2.h
491
+++ b/block/qcow2.h
492
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
493
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
494
void **refcount_table,
495
int64_t *refcount_table_size);
496
+bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
497
+
498
#endif
499
--
64
--
500
1.8.3.1
65
2.37.3
501
502
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Most callback commands in qemu-io return 0 to keep the interpreter
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
loop running, or 1 to quit immediately. However, open_f() just
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
passed through the return value of openfile(), which has different
5
functions where this holds.
6
semantics of returning 0 if a file was opened, or 1 on any failure.
7
6
8
As a result of mixing the return semantics, we are forcing the
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
qemu-io interpreter to exit early on any failures, which is rather
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
annoying when some of the failures are obviously trying to give
9
Message-Id: <20220922084924.201610-22-pbonzini@redhat.com>
11
the user a hint of how to proceed (if we didn't then kill qemu-io
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
out from under the user's feet):
13
14
$ qemu-io
15
qemu-io> open foo
16
qemu-io> open foo
17
file open already, try 'help close'
18
$ echo $?
19
0
20
21
In general, we WANT openfile() to report failures, since it is the
22
function used in the form 'qemu-io -c "$something" no_such_file'
23
for performing one or more -c options on a single file, and it is
24
not worth attempting $something if the file itself cannot be opened.
25
So the solution is to fix open_f() to always return 0 (when we are
26
in interactive mode, even failure to open should not end the
27
session), and save the return value of openfile() for command line
28
use in main().
29
30
Note, however, that we do have some qemu-iotests that do 'qemu-io
31
-c "open file" -c "$something"'; such tests will now proceed to
32
attempt $something whether or not the open succeeded, the same way
33
as if the two commands had been attempted in interactive mode. As
34
such, the expected output for those tests has to be modified. But it
35
also means that it is now possible to use -c close and have a single
36
qemu-io command line operate on more than one file even without
37
using interactive mode. Although the '-c open' action is a subtle
38
change in behavior, remember that qemu-io is for debugging purposes,
39
so as long as it serves the needs of qemu-iotests while still being
40
reasonable for interactive use, it should not be a problem that we
41
are changing tests to the new behavior.
42
43
This has been awkward since at least as far back as commit
44
e3aff4f, in 2009.
45
46
Signed-off-by: Eric Blake <eblake@redhat.com>
47
Reviewed-by: Fam Zheng <famz@redhat.com>
48
Reviewed-by: John Snow <jsnow@redhat.com>
49
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
---
12
---
51
qemu-io.c | 7 ++++---
13
include/qemu/job.h | 2 +-
52
tests/qemu-iotests/060.out | 1 +
14
job.c | 2 +-
53
tests/qemu-iotests/114.out | 5 +++--
15
2 files changed, 2 insertions(+), 2 deletions(-)
54
tests/qemu-iotests/153.out | 6 ++++++
55
4 files changed, 14 insertions(+), 5 deletions(-)
56
16
57
diff --git a/qemu-io.c b/qemu-io.c
17
diff --git a/include/qemu/job.h b/include/qemu/job.h
58
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
59
--- a/qemu-io.c
19
--- a/include/qemu/job.h
60
+++ b/qemu-io.c
20
+++ b/include/qemu/job.h
61
@@ -XXX,XX +XXX,XX @@ static int open_f(BlockBackend *blk, int argc, char **argv)
21
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job);
62
qemu_opts_reset(&empty_opts);
22
*
63
23
* Yield the job coroutine.
64
if (optind == argc - 1) {
24
*/
65
- return openfile(argv[optind], flags, writethrough, force_share, opts);
25
-void job_yield(Job *job);
66
+ openfile(argv[optind], flags, writethrough, force_share, opts);
26
+void coroutine_fn job_yield(Job *job);
67
} else if (optind == argc) {
27
68
- return openfile(NULL, flags, writethrough, force_share, opts);
28
/**
69
+ openfile(NULL, flags, writethrough, force_share, opts);
29
* @job: The job that calls the function.
70
} else {
30
diff --git a/job.c b/job.c
71
QDECREF(opts);
31
index XXXXXXX..XXXXXXX 100644
72
- return qemuio_command_usage(&open_cmd);
32
--- a/job.c
73
+ qemuio_command_usage(&open_cmd);
33
+++ b/job.c
34
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job)
74
}
35
}
75
+ return 0;
76
}
36
}
77
37
78
static int quit_f(BlockBackend *blk, int argc, char **argv)
38
-void job_yield(Job *job)
79
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
39
+void coroutine_fn job_yield(Job *job)
80
index XXXXXXX..XXXXXXX 100644
40
{
81
--- a/tests/qemu-iotests/060.out
41
assert(job->busy);
82
+++ b/tests/qemu-iotests/060.out
83
@@ -XXX,XX +XXX,XX @@ Format specific information:
84
refcount bits: 16
85
corrupt: true
86
can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
87
+no file open, try 'help open'
88
read 512/512 bytes at offset 0
89
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
91
diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out
92
index XXXXXXX..XXXXXXX 100644
93
--- a/tests/qemu-iotests/114.out
94
+++ b/tests/qemu-iotests/114.out
95
@@ -XXX,XX +XXX,XX @@
96
QA output created by 114
97
-Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
98
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
99
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
100
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
101
image: TEST_DIR/t.IMGFMT
102
file format: IMGFMT
103
virtual size: 64M (67108864 bytes)
104
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
105
backing file: TEST_DIR/t.IMGFMT.base
106
backing file format: foo
107
can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo'
108
+no file open, try 'help open'
109
read 4096/4096 bytes at offset 0
110
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
111
*** done
112
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/qemu-iotests/153.out
115
+++ b/tests/qemu-iotests/153.out
116
@@ -XXX,XX +XXX,XX @@ Is another process using the image?
117
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
118
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
119
Is another process using the image?
120
+no file open, try 'help open'
121
122
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
123
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
124
Is another process using the image?
125
+no file open, try 'help open'
126
127
_qemu_img_wrapper info TEST_DIR/t.qcow2
128
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
129
@@ -XXX,XX +XXX,XX @@ _qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
130
131
_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
132
can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
133
+no file open, try 'help open'
134
135
_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
136
137
@@ -XXX,XX +XXX,XX @@ _qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
138
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
139
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
140
Is another process using the image?
141
+no file open, try 'help open'
142
143
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
144
145
@@ -XXX,XX +XXX,XX @@ _qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
146
147
_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
148
can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
149
+no file open, try 'help open'
150
151
_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
152
153
@@ -XXX,XX +XXX,XX @@ _qemu_io_wrapper -U -r -c read 0 512 TEST_DIR/t.qcow2
154
155
_qemu_io_wrapper -c open -U TEST_DIR/t.qcow2 -c read 0 512
156
can't open device TEST_DIR/t.qcow2: force-share=on can only be used with read-only images
157
+no file open, try 'help open'
158
159
_qemu_io_wrapper -c open -r -U TEST_DIR/t.qcow2 -c read 0 512
160
42
161
--
43
--
162
1.8.3.1
44
2.37.3
163
164
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Now that qcow & qcow2 are wired up to get encryption keys
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
via the QCryptoSecret object, nothing is relying on the
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
interactive prompting for passwords. All the code related
5
functions where this holds.
6
to password prompting can thus be ripped out.
7
6
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
Message-Id: <20220922084924.201610-23-pbonzini@redhat.com>
11
Message-id: 20170623162419.26068-17-berrange@redhat.com
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
hmp.c | 31 ---------------------
13
util/qemu-coroutine-lock.c | 14 +++++++-------
15
include/monitor/monitor.h | 7 -----
14
1 file changed, 7 insertions(+), 7 deletions(-)
16
include/qemu/osdep.h | 2 --
17
monitor.c | 68 -----------------------------------------------
18
qapi-schema.json | 10 +------
19
qemu-img.c | 31 ---------------------
20
qemu-io.c | 20 --------------
21
qmp.c | 12 +--------
22
util/oslib-posix.c | 66 ---------------------------------------------
23
util/oslib-win32.c | 24 -----------------
24
10 files changed, 2 insertions(+), 269 deletions(-)
25
15
26
diff --git a/hmp.c b/hmp.c
16
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
27
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
28
--- a/hmp.c
18
--- a/util/qemu-coroutine-lock.c
29
+++ b/hmp.c
19
+++ b/util/qemu-coroutine-lock.c
30
@@ -XXX,XX +XXX,XX @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
20
@@ -XXX,XX +XXX,XX @@ typedef struct CoWaitRecord {
31
g_free(data);
21
QSLIST_ENTRY(CoWaitRecord) next;
22
} CoWaitRecord;
23
24
-static void push_waiter(CoMutex *mutex, CoWaitRecord *w)
25
+static void coroutine_fn push_waiter(CoMutex *mutex, CoWaitRecord *w)
26
{
27
w->co = qemu_coroutine_self();
28
QSLIST_INSERT_HEAD_ATOMIC(&mutex->from_push, w, next);
29
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock)
32
}
30
}
33
31
34
-static void hmp_cont_cb(void *opaque, int err)
32
/* Releases the internal CoMutex. */
35
-{
33
-static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
36
- if (!err) {
34
+static void coroutine_fn qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
37
- qmp_cont(NULL);
38
- }
39
-}
40
-
41
-static bool key_is_missing(const BlockInfo *bdev)
42
-{
43
- return (bdev->inserted && bdev->inserted->encryption_key_missing);
44
-}
45
-
46
void hmp_cont(Monitor *mon, const QDict *qdict)
47
{
35
{
48
- BlockInfoList *bdev_list, *bdev;
36
CoRwTicket *tkt = QSIMPLEQ_FIRST(&lock->tickets);
49
Error *err = NULL;
37
Coroutine *co = NULL;
50
38
@@ -XXX,XX +XXX,XX @@ static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock)
51
- bdev_list = qmp_query_block(NULL);
39
}
52
- for (bdev = bdev_list; bdev; bdev = bdev->next) {
53
- if (key_is_missing(bdev->value)) {
54
- monitor_read_block_device_key(mon, bdev->value->device,
55
- hmp_cont_cb, NULL);
56
- goto out;
57
- }
58
- }
59
-
60
qmp_cont(&err);
61
hmp_handle_error(mon, &err);
62
-
63
-out:
64
- qapi_free_BlockInfoList(bdev_list);
65
}
40
}
66
41
67
void hmp_system_wakeup(Monitor *mon, const QDict *qdict)
42
-void qemu_co_rwlock_rdlock(CoRwlock *lock)
68
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
43
+void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock)
69
qmp_blockdev_change_medium(true, device, false, NULL, target,
44
{
70
!!arg, arg, !!read_only, read_only_mode,
45
Coroutine *self = qemu_coroutine_self();
71
&err);
46
72
- if (err &&
47
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock)
73
- error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
48
self->locks_held++;
74
- error_free(err);
75
- monitor_read_block_device_key(mon, device, NULL, NULL);
76
- return;
77
- }
78
}
79
80
hmp_handle_error(mon, &err);
81
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
82
index XXXXXXX..XXXXXXX 100644
83
--- a/include/monitor/monitor.h
84
+++ b/include/monitor/monitor.h
85
@@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void);
86
int monitor_suspend(Monitor *mon);
87
void monitor_resume(Monitor *mon);
88
89
-int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
90
- BlockCompletionFunc *completion_cb,
91
- void *opaque);
92
-int monitor_read_block_device_key(Monitor *mon, const char *device,
93
- BlockCompletionFunc *completion_cb,
94
- void *opaque);
95
-
96
int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
97
int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp);
98
99
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/qemu/osdep.h
102
+++ b/include/qemu/osdep.h
103
@@ -XXX,XX +XXX,XX @@ void qemu_set_tty_echo(int fd, bool echo);
104
void os_mem_prealloc(int fd, char *area, size_t sz, int smp_cpus,
105
Error **errp);
106
107
-int qemu_read_password(char *buf, int buf_size);
108
-
109
/**
110
* qemu_get_pid_name:
111
* @pid: pid of a process
112
diff --git a/monitor.c b/monitor.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/monitor.c
115
+++ b/monitor.c
116
@@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void)
117
qemu_mutex_unlock(&monitor_lock);
118
}
49
}
119
50
120
-static void bdrv_password_cb(void *opaque, const char *password,
51
-void qemu_co_rwlock_unlock(CoRwlock *lock)
121
- void *readline_opaque)
52
+void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock)
122
-{
53
{
123
- Monitor *mon = opaque;
54
Coroutine *self = qemu_coroutine_self();
124
- BlockDriverState *bs = readline_opaque;
55
125
- int ret = 0;
56
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
126
- Error *local_err = NULL;
57
qemu_co_rwlock_maybe_wake_one(lock);
127
-
128
- bdrv_add_key(bs, password, &local_err);
129
- if (local_err) {
130
- error_report_err(local_err);
131
- ret = -EPERM;
132
- }
133
- if (mon->password_completion_cb)
134
- mon->password_completion_cb(mon->password_opaque, ret);
135
-
136
- monitor_read_command(mon, 1);
137
-}
138
-
139
-int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
140
- BlockCompletionFunc *completion_cb,
141
- void *opaque)
142
-{
143
- int err;
144
-
145
- monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
146
- bdrv_get_encrypted_filename(bs));
147
-
148
- mon->password_completion_cb = completion_cb;
149
- mon->password_opaque = opaque;
150
-
151
- err = monitor_read_password(mon, bdrv_password_cb, bs);
152
-
153
- if (err && completion_cb)
154
- completion_cb(opaque, err);
155
-
156
- return err;
157
-}
158
-
159
-int monitor_read_block_device_key(Monitor *mon, const char *device,
160
- BlockCompletionFunc *completion_cb,
161
- void *opaque)
162
-{
163
- Error *err = NULL;
164
- BlockBackend *blk;
165
-
166
- blk = blk_by_name(device);
167
- if (!blk) {
168
- monitor_printf(mon, "Device not found %s\n", device);
169
- return -1;
170
- }
171
- if (!blk_bs(blk)) {
172
- monitor_printf(mon, "Device '%s' has no medium\n", device);
173
- return -1;
174
- }
175
-
176
- bdrv_add_key(blk_bs(blk), NULL, &err);
177
- if (err) {
178
- error_free(err);
179
- return monitor_read_bdrv_key_start(mon, blk_bs(blk), completion_cb, opaque);
180
- }
181
-
182
- if (completion_cb) {
183
- completion_cb(opaque, 0);
184
- }
185
- return 0;
186
-}
187
-
188
QemuOptsList qemu_mon_opts = {
189
.name = "mon",
190
.implied_opt_name = "chardev",
191
diff --git a/qapi-schema.json b/qapi-schema.json
192
index XXXXXXX..XXXXXXX 100644
193
--- a/qapi-schema.json
194
+++ b/qapi-schema.json
195
@@ -XXX,XX +XXX,XX @@
196
# Since: 0.14.0
197
#
198
# Returns: If successful, nothing
199
-# If QEMU was started with an encrypted block device and a key has
200
-# not yet been set, DeviceEncrypted.
201
#
202
# Notes: This command will succeed if the guest is currently running. It
203
# will also succeed if the guest is in the "inmigrate" state; in
204
@@ -XXX,XX +XXX,XX @@
205
# * This command is stateless, this means that commands that depend
206
# on state information (such as getfd) might not work
207
#
208
-# * Commands that prompt the user for data (eg. 'cont' when the block
209
-# device is encrypted) don't currently work
210
+# * Commands that prompt the user for data don't currently work
211
#
212
# Example:
213
#
214
@@ -XXX,XX +XXX,XX @@
215
#
216
# Returns: Nothing on success.
217
# If @device is not a valid block device, DeviceNotFound
218
-# If the new block device is encrypted, DeviceEncrypted. Note that
219
-# if this error is returned, the device has been opened successfully
220
-# and an additional call to @block_passwd is required to set the
221
-# device's password. The behavior of reads and writes to the block
222
-# device between when these calls are executed is undefined.
223
#
224
# Notes: This interface is deprecated, and it is strongly recommended that you
225
# avoid using it. For changing block devices, use
226
diff --git a/qemu-img.c b/qemu-img.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/qemu-img.c
229
+++ b/qemu-img.c
230
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
231
}
58
}
232
59
233
60
-void qemu_co_rwlock_downgrade(CoRwlock *lock)
234
-static int img_open_password(BlockBackend *blk, const char *filename,
61
+void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock)
235
- int flags, bool quiet)
62
{
236
-{
63
qemu_co_mutex_lock(&lock->mutex);
237
- BlockDriverState *bs;
64
assert(lock->owners == -1);
238
- char password[256];
65
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_downgrade(CoRwlock *lock)
239
-
66
qemu_co_rwlock_maybe_wake_one(lock);
240
- bs = blk_bs(blk);
241
- if (bdrv_is_encrypted(bs) && bdrv_key_required(bs) &&
242
- !(flags & BDRV_O_NO_IO)) {
243
- qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
244
- if (qemu_read_password(password, sizeof(password)) < 0) {
245
- error_report("No password given");
246
- return -1;
247
- }
248
- if (bdrv_set_key(bs, password) < 0) {
249
- error_report("invalid password");
250
- return -1;
251
- }
252
- }
253
- return 0;
254
-}
255
-
256
-
257
static BlockBackend *img_open_opts(const char *optstr,
258
QemuOpts *opts, int flags, bool writethrough,
259
bool quiet, bool force_share)
260
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_opts(const char *optstr,
261
}
262
blk_set_enable_write_cache(blk, !writethrough);
263
264
- if (img_open_password(blk, optstr, flags, quiet) < 0) {
265
- blk_unref(blk);
266
- return NULL;
267
- }
268
return blk;
269
}
67
}
270
68
271
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_file(const char *filename,
69
-void qemu_co_rwlock_wrlock(CoRwlock *lock)
272
}
70
+void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock)
273
blk_set_enable_write_cache(blk, !writethrough);
71
{
274
72
Coroutine *self = qemu_coroutine_self();
275
- if (img_open_password(blk, filename, flags, quiet) < 0) {
73
276
- blk_unref(blk);
74
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_wrlock(CoRwlock *lock)
277
- return NULL;
75
self->locks_held++;
278
- }
279
return blk;
280
}
76
}
281
77
282
diff --git a/qemu-io.c b/qemu-io.c
78
-void qemu_co_rwlock_upgrade(CoRwlock *lock)
283
index XXXXXXX..XXXXXXX 100644
79
+void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock)
284
--- a/qemu-io.c
285
+++ b/qemu-io.c
286
@@ -XXX,XX +XXX,XX @@ static int openfile(char *name, int flags, bool writethrough, bool force_share,
287
QDict *opts)
288
{
80
{
289
Error *local_err = NULL;
81
qemu_co_mutex_lock(&lock->mutex);
290
- BlockDriverState *bs;
82
assert(lock->owners > 0);
291
292
if (qemuio_blk) {
293
error_report("file open already, try 'help close'");
294
@@ -XXX,XX +XXX,XX @@ static int openfile(char *name, int flags, bool writethrough, bool force_share,
295
return 1;
296
}
297
298
- bs = blk_bs(qemuio_blk);
299
- if (bdrv_is_encrypted(bs) && bdrv_key_required(bs)) {
300
- char password[256];
301
- printf("Disk image '%s' is encrypted.\n", name);
302
- if (qemu_read_password(password, sizeof(password)) < 0) {
303
- error_report("No password given");
304
- goto error;
305
- }
306
- if (bdrv_set_key(bs, password) < 0) {
307
- error_report("invalid password");
308
- goto error;
309
- }
310
- }
311
-
312
blk_set_enable_write_cache(qemuio_blk, !writethrough);
313
314
return 0;
315
-
316
- error:
317
- blk_unref(qemuio_blk);
318
- qemuio_blk = NULL;
319
- return 1;
320
}
321
322
static void open_help(void)
323
diff --git a/qmp.c b/qmp.c
324
index XXXXXXX..XXXXXXX 100644
325
--- a/qmp.c
326
+++ b/qmp.c
327
@@ -XXX,XX +XXX,XX @@ SpiceInfo *qmp_query_spice(Error **errp)
328
329
void qmp_cont(Error **errp)
330
{
331
- Error *local_err = NULL;
332
BlockBackend *blk;
333
- BlockDriverState *bs;
334
- BdrvNextIterator it;
335
+ Error *local_err = NULL;
336
337
/* if there is a dump in background, we should wait until the dump
338
* finished */
339
@@ -XXX,XX +XXX,XX @@ void qmp_cont(Error **errp)
340
blk_iostatus_reset(blk);
341
}
342
343
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
344
- bdrv_add_key(bs, NULL, &local_err);
345
- if (local_err) {
346
- error_propagate(errp, local_err);
347
- return;
348
- }
349
- }
350
-
351
/* Continuing after completed migration. Images have been inactivated to
352
* allow the destination to take control. Need to get control back now.
353
*
354
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
355
index XXXXXXX..XXXXXXX 100644
356
--- a/util/oslib-posix.c
357
+++ b/util/oslib-posix.c
358
@@ -XXX,XX +XXX,XX @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
359
}
360
361
362
-static struct termios oldtty;
363
-
364
-static void term_exit(void)
365
-{
366
- tcsetattr(0, TCSANOW, &oldtty);
367
-}
368
-
369
-static void term_init(void)
370
-{
371
- struct termios tty;
372
-
373
- tcgetattr(0, &tty);
374
- oldtty = tty;
375
-
376
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
377
- |INLCR|IGNCR|ICRNL|IXON);
378
- tty.c_oflag |= OPOST;
379
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
380
- tty.c_cflag &= ~(CSIZE|PARENB);
381
- tty.c_cflag |= CS8;
382
- tty.c_cc[VMIN] = 1;
383
- tty.c_cc[VTIME] = 0;
384
-
385
- tcsetattr(0, TCSANOW, &tty);
386
-
387
- atexit(term_exit);
388
-}
389
-
390
-int qemu_read_password(char *buf, int buf_size)
391
-{
392
- uint8_t ch;
393
- int i, ret;
394
-
395
- printf("password: ");
396
- fflush(stdout);
397
- term_init();
398
- i = 0;
399
- for (;;) {
400
- ret = read(0, &ch, 1);
401
- if (ret == -1) {
402
- if (errno == EAGAIN || errno == EINTR) {
403
- continue;
404
- } else {
405
- break;
406
- }
407
- } else if (ret == 0) {
408
- ret = -1;
409
- break;
410
- } else {
411
- if (ch == '\r' ||
412
- ch == '\n') {
413
- ret = 0;
414
- break;
415
- }
416
- if (i < (buf_size - 1)) {
417
- buf[i++] = ch;
418
- }
419
- }
420
- }
421
- term_exit();
422
- buf[i] = '\0';
423
- printf("\n");
424
- return ret;
425
-}
426
-
427
-
428
char *qemu_get_pid_name(pid_t pid)
429
{
430
char *name = NULL;
431
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
432
index XXXXXXX..XXXXXXX 100644
433
--- a/util/oslib-win32.c
434
+++ b/util/oslib-win32.c
435
@@ -XXX,XX +XXX,XX @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus,
436
}
437
438
439
-/* XXX: put correct support for win32 */
440
-int qemu_read_password(char *buf, int buf_size)
441
-{
442
- int c, i;
443
-
444
- printf("Password: ");
445
- fflush(stdout);
446
- i = 0;
447
- for (;;) {
448
- c = getchar();
449
- if (c < 0) {
450
- buf[i] = '\0';
451
- return -1;
452
- } else if (c == '\n') {
453
- break;
454
- } else if (i < (buf_size - 1)) {
455
- buf[i++] = c;
456
- }
457
- }
458
- buf[i] = '\0';
459
- return 0;
460
-}
461
-
462
-
463
char *qemu_get_pid_name(pid_t pid)
464
{
465
/* XXX Implement me */
466
--
83
--
467
1.8.3.1
84
2.37.3
468
469
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The lone caller that cares about a return of BDRV_BLOCK_RAW
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
(namely, io.c:bdrv_co_get_block_status) completely replaces the
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
return value, so there is no point in passing BDRV_BLOCK_DATA.
5
functions where this holds.
6
6
7
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-Id: <20220922084924.201610-24-pbonzini@redhat.com>
10
[kwolf: Fixed up coding style]
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
13
---
12
block/commit.c | 2 +-
14
block/raw-format.c | 3 ++-
13
block/mirror.c | 2 +-
15
1 file changed, 2 insertions(+), 1 deletion(-)
14
block/raw-format.c | 2 +-
15
block/vpc.c | 2 +-
16
include/block/block.h | 6 +++---
17
5 files changed, 7 insertions(+), 7 deletions(-)
18
16
19
diff --git a/block/commit.c b/block/commit.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/commit.c
22
+++ b/block/commit.c
23
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_commit_top_get_block_status(
24
{
25
*pnum = nb_sectors;
26
*file = bs->backing->bs;
27
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
28
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
29
(sector_num << BDRV_SECTOR_BITS);
30
}
31
32
diff --git a/block/mirror.c b/block/mirror.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/mirror.c
35
+++ b/block/mirror.c
36
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_mirror_top_get_block_status(
37
{
38
*pnum = nb_sectors;
39
*file = bs->backing->bs;
40
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
41
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
42
(sector_num << BDRV_SECTOR_BITS);
43
}
44
45
diff --git a/block/raw-format.c b/block/raw-format.c
17
diff --git a/block/raw-format.c b/block/raw-format.c
46
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
47
--- a/block/raw-format.c
19
--- a/block/raw-format.c
48
+++ b/block/raw-format.c
20
+++ b/block/raw-format.c
49
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static void raw_lock_medium(BlockDriverState *bs, bool locked)
50
*pnum = nb_sectors;
22
bdrv_lock_medium(bs->file->bs, locked);
51
*file = bs->file->bs;
52
sector_num += s->offset / BDRV_SECTOR_SIZE;
53
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
54
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
55
(sector_num << BDRV_SECTOR_BITS);
56
}
23
}
57
24
58
diff --git a/block/vpc.c b/block/vpc.c
25
-static int raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
59
index XXXXXXX..XXXXXXX 100644
26
+static int coroutine_fn raw_co_ioctl(BlockDriverState *bs,
60
--- a/block/vpc.c
27
+ unsigned long int req, void *buf)
61
+++ b/block/vpc.c
28
{
62
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn vpc_co_get_block_status(BlockDriverState *bs,
29
BDRVRawState *s = bs->opaque;
63
if (be32_to_cpu(footer->type) == VHD_FIXED) {
30
if (s->offset || s->has_size) {
64
*pnum = nb_sectors;
65
*file = bs->file->bs;
66
- return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA |
67
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
68
(sector_num << BDRV_SECTOR_BITS);
69
}
70
71
diff --git a/include/block/block.h b/include/block/block.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block.h
74
+++ b/include/block/block.h
75
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
76
* BDRV_BLOCK_EOF: the returned pnum covers through end of file for this layer
77
*
78
* Internal flag:
79
- * BDRV_BLOCK_RAW: used internally to indicate that the request was
80
- * answered by a passthrough driver such as raw and that the
81
- * block layer should recompute the answer from bs->file.
82
+ * BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request
83
+ * that the block layer recompute the answer from the returned
84
+ * BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
85
*
86
* If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 (BDRV_BLOCK_OFFSET_MASK)
87
* represent the offset in the returned BDS that is allocated for the
88
--
31
--
89
1.8.3.1
32
2.37.3
90
91
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
2
3
- offset_to_bootsector is the number of sectors up to FAT bootsector
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
- offset_to_fat is the number of sectors up to first File Allocation Table
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
- offset_to_root_dir is the number of sectors up to root directory sector
5
functions where this holds.
6
6
7
Replace first_sectors_number - 1 by offset_to_bootsector.
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Replace first_sectors_number by offset_to_fat.
8
Acked-by: Greg Kurz <groug@kaod.org>
9
Replace faked_sectors by offset_to_rootdir.
9
Reviewed-by: Alberto Faria <afaria@redhat.com>
10
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
11
Message-Id: <20220922084924.201610-25-pbonzini@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
---
14
block/vvfat.c | 70 ++++++++++++++++++++++++++++++++++++-----------------------
15
hw/9pfs/9p.h | 9 ++++++---
15
1 file changed, 43 insertions(+), 27 deletions(-)
16
1 file changed, 6 insertions(+), 3 deletions(-)
16
17
17
diff --git a/block/vvfat.c b/block/vvfat.c
18
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vvfat.c
20
--- a/hw/9pfs/9p.h
20
+++ b/block/vvfat.c
21
+++ b/hw/9pfs/9p.h
21
@@ -XXX,XX +XXX,XX @@ static void print_mapping(const struct mapping_t* mapping);
22
@@ -XXX,XX +XXX,XX @@ typedef struct V9fsGetlock
22
typedef struct BDRVVVFATState {
23
extern int open_fd_hw;
23
CoMutex lock;
24
extern int total_open_fd;
24
BlockDriverState* bs; /* pointer to parent */
25
25
- unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
26
-static inline void v9fs_path_write_lock(V9fsState *s)
26
unsigned char first_sectors[0x40*0x200];
27
+static inline void coroutine_fn
27
28
+v9fs_path_write_lock(V9fsState *s)
28
int fat_type; /* 16 or 32 */
29
array_t fat,directory,mapping;
30
char volume_label[11];
31
32
+ uint32_t offset_to_bootsector; /* 0 for floppy, 0x3f for disk */
33
+
34
unsigned int cluster_size;
35
unsigned int sectors_per_cluster;
36
unsigned int sectors_per_fat;
37
unsigned int sectors_of_root_directory;
38
uint32_t last_cluster_of_root_directory;
39
- unsigned int faked_sectors; /* how many sectors are faked before file data */
40
uint32_t sector_count; /* total number of sectors of the partition */
41
uint32_t cluster_count; /* total number of clusters of this partition */
42
uint32_t max_fat_value;
43
+ uint32_t offset_to_fat;
44
+ uint32_t offset_to_root_dir;
45
46
int current_fd;
47
mapping_t* current_mapping;
48
@@ -XXX,XX +XXX,XX @@ static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
49
partition->attributes=0x80; /* bootable */
50
51
/* LBA is used when partition is outside the CHS geometry */
52
- lba = sector2CHS(&partition->start_CHS, s->first_sectors_number - 1,
53
+ lba = sector2CHS(&partition->start_CHS, s->offset_to_bootsector,
54
cyls, heads, secs);
55
lba |= sector2CHS(&partition->end_CHS, s->bs->total_sectors - 1,
56
cyls, heads, secs);
57
58
/*LBA partitions are identified only by start/length_sector_long not by CHS*/
59
- partition->start_sector_long = cpu_to_le32(s->first_sectors_number - 1);
60
+ partition->start_sector_long = cpu_to_le32(s->offset_to_bootsector);
61
partition->length_sector_long = cpu_to_le32(s->bs->total_sectors
62
- - s->first_sectors_number + 1);
63
+ - s->offset_to_bootsector);
64
65
/* FAT12/FAT16/FAT32 */
66
/* DOS uses different types when partition is LBA,
67
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
68
69
static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
70
{
29
{
71
- return (sector_num-s->faked_sectors)/s->sectors_per_cluster;
30
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
72
+ return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
31
qemu_co_rwlock_wrlock(&s->rename_lock);
32
}
73
}
33
}
74
34
75
static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num)
35
-static inline void v9fs_path_read_lock(V9fsState *s)
36
+static inline void coroutine_fn
37
+v9fs_path_read_lock(V9fsState *s)
76
{
38
{
77
- return s->faked_sectors + s->sectors_per_cluster * cluster_num;
39
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
78
+ return s->offset_to_root_dir + s->sectors_per_cluster * cluster_num;
40
qemu_co_rwlock_rdlock(&s->rename_lock);
41
}
79
}
42
}
80
43
81
static int init_directories(BDRVVVFATState* s,
44
-static inline void v9fs_path_unlock(V9fsState *s)
82
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
45
+static inline void coroutine_fn
83
i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
46
+v9fs_path_unlock(V9fsState *s)
84
s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
47
{
85
48
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
86
+ s->offset_to_fat = s->offset_to_bootsector + 1;
49
qemu_co_rwlock_unlock(&s->rename_lock);
87
+ s->offset_to_root_dir = s->offset_to_fat + s->sectors_per_fat * 2;
88
+
89
array_init(&(s->mapping),sizeof(mapping_t));
90
array_init(&(s->directory),sizeof(direntry_t));
91
92
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
93
/* Now build FAT, and write back information into directory */
94
init_fat(s);
95
96
- s->faked_sectors=s->first_sectors_number+s->sectors_per_fat*2;
97
s->cluster_count=sector2cluster(s, s->sector_count);
98
99
mapping = array_get_next(&(s->mapping));
100
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
101
102
s->current_mapping = NULL;
103
104
- bootsector=(bootsector_t*)(s->first_sectors+(s->first_sectors_number-1)*0x200);
105
+ bootsector = (bootsector_t *)(s->first_sectors
106
+ + s->offset_to_bootsector * 0x200);
107
bootsector->jump[0]=0xeb;
108
bootsector->jump[1]=0x3e;
109
bootsector->jump[2]=0x90;
110
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
111
bootsector->number_of_fats=0x2; /* number of FATs */
112
bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
113
bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
114
- bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
115
+ /* media descriptor: hard disk=0xf8, floppy=0xf0 */
116
+ bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
117
s->fat.pointer[0] = bootsector->media_type;
118
bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
119
bootsector->sectors_per_track = cpu_to_le16(secs);
120
bootsector->number_of_heads = cpu_to_le16(heads);
121
- bootsector->hidden_sectors=cpu_to_le32(s->first_sectors_number==1?0:0x3f);
122
+ bootsector->hidden_sectors = cpu_to_le32(s->offset_to_bootsector);
123
bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
124
125
/* LATER TODO: if FAT32, this is wrong */
126
- bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
127
+ /* drive_number: fda=0, hda=0x80 */
128
+ bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80;
129
bootsector->u.fat16.current_head=0;
130
bootsector->u.fat16.signature=0x29;
131
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
132
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
133
secs = s->fat_type == 12 ? 18 : 36;
134
s->sectors_per_cluster = 1;
135
}
136
- s->first_sectors_number = 1;
137
cyls = 80;
138
heads = 2;
139
} else {
140
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
141
if (!s->fat_type) {
142
s->fat_type = 16;
143
}
144
- s->first_sectors_number = 0x40;
145
+ s->offset_to_bootsector = 0x3f;
146
cyls = s->fat_type == 12 ? 64 : 1024;
147
heads = 16;
148
secs = 63;
149
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
150
fprintf(stderr, "vvfat %s chs %d,%d,%d\n",
151
dirname, cyls, heads, secs);
152
153
- s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
154
+ s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
155
156
if (qemu_opt_get_bool(opts, "rw", false)) {
157
if (!bdrv_is_read_only(bs)) {
158
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
159
goto fail;
160
}
161
162
- s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
163
+ s->sector_count = s->offset_to_root_dir
164
+ + s->sectors_per_cluster * s->cluster_count;
165
166
/* Disable migration when vvfat is used rw */
167
if (s->qcow) {
168
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
169
}
170
}
171
172
- if (s->first_sectors_number == 0x40) {
173
+ if (s->offset_to_bootsector > 0) {
174
init_mbr(s, cyls, heads, secs);
175
}
176
177
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
178
}
179
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
180
}
181
- if(sector_num<s->faked_sectors) {
182
- if(sector_num<s->first_sectors_number)
183
- memcpy(buf+i*0x200,&(s->first_sectors[sector_num*0x200]),0x200);
184
- else if(sector_num-s->first_sectors_number<s->sectors_per_fat)
185
- memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number)*0x200]),0x200);
186
- else if(sector_num-s->first_sectors_number-s->sectors_per_fat<s->sectors_per_fat)
187
- memcpy(buf+i*0x200,&(s->fat.pointer[(sector_num-s->first_sectors_number-s->sectors_per_fat)*0x200]),0x200);
188
+ if (sector_num < s->offset_to_root_dir) {
189
+ if (sector_num < s->offset_to_fat) {
190
+ memcpy(buf + i * 0x200,
191
+ &(s->first_sectors[sector_num * 0x200]),
192
+ 0x200);
193
+ } else if (sector_num < s->offset_to_fat + s->sectors_per_fat) {
194
+ memcpy(buf + i * 0x200,
195
+ &(s->fat.pointer[(sector_num
196
+ - s->offset_to_fat) * 0x200]),
197
+ 0x200);
198
+ } else if (sector_num < s->offset_to_root_dir) {
199
+ memcpy(buf + i * 0x200,
200
+ &(s->fat.pointer[(sector_num - s->offset_to_fat
201
+ - s->sectors_per_fat) * 0x200]),
202
+ 0x200);
203
+ }
204
} else {
205
- uint32_t sector=sector_num-s->faked_sectors,
206
+ uint32_t sector = sector_num - s->offset_to_root_dir,
207
sector_offset_in_cluster=(sector%s->sectors_per_cluster),
208
cluster_num=sector/s->sectors_per_cluster;
209
if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
210
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
211
memcpy(s->fat2, s->fat.pointer, size);
212
}
213
check = vvfat_read(s->bs,
214
- s->first_sectors_number, s->fat2, s->sectors_per_fat);
215
+ s->offset_to_fat, s->fat2, s->sectors_per_fat);
216
if (check) {
217
fprintf(stderr, "Could not copy fat\n");
218
return 0;
219
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
220
* - do not allow to write non-ASCII filenames
221
*/
222
223
- if (sector_num < s->first_sectors_number)
224
+ if (sector_num < s->offset_to_fat)
225
return -1;
226
227
for (i = sector2cluster(s, sector_num);
228
--
50
--
229
1.8.3.1
51
2.37.3
230
52
231
53
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
2
3
More specifically:
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
- try without numeric-tail only if LFN didn't have invalid short chars
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
- start at ~1 (instead of ~0)
5
functions where this holds.
6
- handle case if numeric tail is more than one char (ie > 10)
7
6
8
Windows 9x Scandisk doesn't see anymore mismatches between short file names and
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
long file names for non-ASCII filenames.
8
Reviewed-by: Juan Quintela <quintela@redhat.com>
10
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Specification: "FAT: General overview of on-disk format" v1.03, page 31
10
Reviewed-by: Alberto Faria <afaria@redhat.com>
12
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-Id: <20220922084924.201610-26-pbonzini@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
---
15
block/vvfat.c | 65 ++++++++++++++++++++++++++++-------------------------------
16
migration/migration.c | 3 ++-
16
1 file changed, 31 insertions(+), 34 deletions(-)
17
1 file changed, 2 insertions(+), 1 deletion(-)
17
18
18
diff --git a/block/vvfat.c b/block/vvfat.c
19
diff --git a/migration/migration.c b/migration/migration.c
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/block/vvfat.c
21
--- a/migration/migration.c
21
+++ b/block/vvfat.c
22
+++ b/migration/migration.c
22
@@ -XXX,XX +XXX,XX @@ static uint8_t to_valid_short_char(gunichar c)
23
@@ -XXX,XX +XXX,XX @@ static void process_incoming_migration_bh(void *opaque)
24
migration_incoming_state_destroy();
23
}
25
}
24
26
25
static direntry_t *create_short_filename(BDRVVVFATState *s,
27
-static void process_incoming_migration_co(void *opaque)
26
- const char *filename)
28
+static void coroutine_fn
27
+ const char *filename,
29
+process_incoming_migration_co(void *opaque)
28
+ unsigned int directory_start)
29
{
30
{
30
- int j = 0;
31
MigrationIncomingState *mis = migration_incoming_get_current();
31
+ int i, j = 0;
32
PostcopyState ps;
32
direntry_t *entry = array_get_next(&(s->directory));
33
const gchar *p, *last_dot = NULL;
34
gunichar c;
35
bool lossy_conversion = false;
36
+ char tail[11];
37
38
if (!entry) {
39
return NULL;
40
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_short_filename(BDRVVVFATState *s,
41
}
42
}
43
}
44
- (void)lossy_conversion;
45
- return entry;
46
+
47
+ /* numeric-tail generation */
48
+ for (j = 0; j < 8; j++) {
49
+ if (entry->name[j] == ' ') {
50
+ break;
51
+ }
52
+ }
53
+ for (i = lossy_conversion ? 1 : 0; i < 999999; i++) {
54
+ direntry_t *entry1;
55
+ if (i > 0) {
56
+ int len = sprintf(tail, "~%d", i);
57
+ memcpy(entry->name + MIN(j, 8 - len), tail, len);
58
+ }
59
+ for (entry1 = array_get(&(s->directory), directory_start);
60
+ entry1 < entry; entry1++) {
61
+ if (!is_long_name(entry1) &&
62
+ !memcmp(entry1->name, entry->name, 11)) {
63
+ break; /* found dupe */
64
+ }
65
+ }
66
+ if (entry1 == entry) {
67
+ /* no dupe found */
68
+ return entry;
69
+ }
70
+ }
71
+ return NULL;
72
}
73
74
/* fat functions */
75
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
76
}
77
78
entry_long=create_long_filename(s,filename);
79
- entry = create_short_filename(s, filename);
80
-
81
- /* mangle duplicates */
82
- while(1) {
83
- direntry_t* entry1=array_get(&(s->directory),directory_start);
84
- int j;
85
-
86
- for(;entry1<entry;entry1++)
87
- if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))
88
- break; /* found dupe */
89
- if(entry1==entry) /* no dupe found */
90
- break;
91
-
92
- /* use all 8 characters of name */
93
- if(entry->name[7]==' ') {
94
- int j;
95
- for(j=6;j>0 && entry->name[j]==' ';j--)
96
- entry->name[j]='~';
97
- }
98
-
99
- /* increment number */
100
- for(j=7;j>0 && entry->name[j]=='9';j--)
101
- entry->name[j]='0';
102
- if(j>0) {
103
- if(entry->name[j]<'0' || entry->name[j]>'9')
104
- entry->name[j]='0';
105
- else
106
- entry->name[j]++;
107
- }
108
- }
109
+ entry = create_short_filename(s, filename, directory_start);
110
111
/* calculate checksum; propagate to long name */
112
if(entry_long) {
113
--
33
--
114
1.8.3.1
34
2.37.3
115
35
116
36
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Marc-André Lureau <marcandre.lureau@redhat.com>
2
2
3
Without a passthrough status of BDRV_BLOCK_RAW, anything wrapped by
3
Callers of coroutine_fn must be coroutine_fn themselves, or the call
4
blkdebug appears 100% allocated as data. Better is treating it the
4
must be within "if (qemu_in_coroutine())". Apply coroutine_fn to
5
same as the underlying file being wrapped.
5
functions where this holds.
6
6
7
Update iotest 177 for the new expected output.
7
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
8
Reviewed-by: Alberto Faria <afaria@redhat.com>
9
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Message-Id: <20220922084924.201610-27-pbonzini@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
13
---
15
block/blkdebug.c | 11 +++++++++++
14
tests/unit/test-coroutine.c | 2 +-
16
tests/qemu-iotests/177.out | 5 ++++-
15
1 file changed, 1 insertion(+), 1 deletion(-)
17
2 files changed, 15 insertions(+), 1 deletion(-)
18
16
19
diff --git a/block/blkdebug.c b/block/blkdebug.c
17
diff --git a/tests/unit/test-coroutine.c b/tests/unit/test-coroutine.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/block/blkdebug.c
19
--- a/tests/unit/test-coroutine.c
22
+++ b/block/blkdebug.c
20
+++ b/tests/unit/test-coroutine.c
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blkdebug_co_pdiscard(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static void perf_baseline(void)
24
return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
22
g_test_message("Function call %u iterations: %f s", maxcycles, duration);
25
}
23
}
26
24
27
+static int64_t coroutine_fn blkdebug_co_get_block_status(
25
-static __attribute__((noinline)) void perf_cost_func(void *opaque)
28
+ BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum,
26
+static __attribute__((noinline)) void coroutine_fn perf_cost_func(void *opaque)
29
+ BlockDriverState **file)
30
+{
31
+ *pnum = nb_sectors;
32
+ *file = bs->file->bs;
33
+ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID |
34
+ (sector_num << BDRV_SECTOR_BITS);
35
+}
36
+
37
static void blkdebug_close(BlockDriverState *bs)
38
{
27
{
39
BDRVBlkdebugState *s = bs->opaque;
28
qemu_coroutine_yield();
40
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
29
}
41
.bdrv_co_flush_to_disk = blkdebug_co_flush,
42
.bdrv_co_pwrite_zeroes = blkdebug_co_pwrite_zeroes,
43
.bdrv_co_pdiscard = blkdebug_co_pdiscard,
44
+ .bdrv_co_get_block_status = blkdebug_co_get_block_status,
45
46
.bdrv_debug_event = blkdebug_debug_event,
47
.bdrv_debug_breakpoint = blkdebug_debug_breakpoint,
48
diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out
49
index XXXXXXX..XXXXXXX 100644
50
--- a/tests/qemu-iotests/177.out
51
+++ b/tests/qemu-iotests/177.out
52
@@ -XXX,XX +XXX,XX @@ read 30408704/30408704 bytes at offset 80740352
53
read 23068672/23068672 bytes at offset 111149056
54
22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
55
Offset Length File
56
-0 0x8000000 json:{"image": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}, "driver": "blkdebug", "align": "4k"}
57
+0 0x800000 TEST_DIR/t.IMGFMT
58
+0x900000 0x2400000 TEST_DIR/t.IMGFMT
59
+0x3c00000 0x1100000 TEST_DIR/t.IMGFMT
60
+0x6a00000 0x1600000 TEST_DIR/t.IMGFMT
61
No errors were found on the image.
62
*** done
63
--
30
--
64
1.8.3.1
31
2.37.3
65
32
66
33
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
2
Message-Id: <20221006122607.162769-1-kwolf@redhat.com>
3
We document that *file is valid if the return is not an error and
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
includes BDRV_BLOCK_OFFSET_VALID, but forgot to obey this contract
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
when a driver (such as blkdebug) lacks a callback. Messed up in
6
commit 67a0fd2 (v2.6), when we added the file parameter.
7
8
Enhance qemu-iotest 177 to cover this, using a sequence that would
9
print garbage or even SEGV, because it was dererefencing through
10
uninitialized memory. [The resulting test output shows that we
11
have less-than-ideal block status from the blkdebug driver, but
12
that's a separate fix coming up soon.]
13
14
Setting *file on all paths that return BDRV_BLOCK_OFFSET_VALID is
15
enough to fix the crash, but we can go one step further: always
16
setting *file, even on error, means that a broken caller that
17
blindly dereferences file without checking for error is now more
18
likely to get a reliable SEGV instead of randomly acting on garbage,
19
making it easier to diagnose such buggy callers. Adding an
20
assertion that file is set where expected doesn't hurt either.
21
22
CC: qemu-stable@nongnu.org
23
Signed-off-by: Eric Blake <eblake@redhat.com>
24
Reviewed-by: Fam Zheng <famz@redhat.com>
25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Reviewed-by: John Snow <jsnow@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
---
6
---
29
block/io.c | 5 +++--
7
block/quorum.c | 2 --
30
tests/qemu-iotests/177 | 3 +++
8
1 file changed, 2 deletions(-)
31
tests/qemu-iotests/177.out | 2 ++
32
3 files changed, 8 insertions(+), 2 deletions(-)
33
9
34
diff --git a/block/io.c b/block/io.c
10
diff --git a/block/quorum.c b/block/quorum.c
35
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
36
--- a/block/io.c
12
--- a/block/quorum.c
37
+++ b/block/io.c
13
+++ b/block/quorum.c
38
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
14
@@ -XXX,XX +XXX,XX @@ static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb)
39
int64_t n;
15
return false;
40
int64_t ret, ret2;
41
42
+ *file = NULL;
43
total_sectors = bdrv_nb_sectors(bs);
44
if (total_sectors < 0) {
45
return total_sectors;
46
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
47
}
48
if (bs->drv->protocol_name) {
49
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
50
+ *file = bs;
51
}
52
return ret;
53
}
54
55
- *file = NULL;
56
bdrv_inc_in_flight(bs);
57
ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum,
58
file);
59
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
60
}
61
62
if (ret & BDRV_BLOCK_RAW) {
63
- assert(ret & BDRV_BLOCK_OFFSET_VALID);
64
+ assert(ret & BDRV_BLOCK_OFFSET_VALID && *file);
65
ret = bdrv_co_get_block_status(*file, ret >> BDRV_SECTOR_BITS,
66
*pnum, pnum, file);
67
goto out;
68
diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177
69
index XXXXXXX..XXXXXXX 100755
70
--- a/tests/qemu-iotests/177
71
+++ b/tests/qemu-iotests/177
72
@@ -XXX,XX +XXX,XX @@ _supported_proto file
73
CLUSTER_SIZE=1M
74
size=128M
75
options=driver=blkdebug,image.driver=qcow2
76
+nested_opts=image.file.driver=file,image.file.filename=$TEST_IMG
77
78
echo
79
echo "== setting up files =="
80
@@ -XXX,XX +XXX,XX @@ function verify_io()
81
}
16
}
82
17
83
verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
18
-static int read_fifo_child(QuorumAIOCB *acb);
84
+$QEMU_IMG map --image-opts "$options,$nested_opts,align=4k" \
19
-
85
+ | _filter_qemu_img_map
20
static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source)
86
21
{
87
_check_test_img
22
int i;
88
89
diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out
90
index XXXXXXX..XXXXXXX 100644
91
--- a/tests/qemu-iotests/177.out
92
+++ b/tests/qemu-iotests/177.out
93
@@ -XXX,XX +XXX,XX @@ read 30408704/30408704 bytes at offset 80740352
94
29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
95
read 23068672/23068672 bytes at offset 111149056
96
22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
97
+Offset Length File
98
+0 0x8000000 json:{"image": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}, "driver": "blkdebug", "align": "4k"}
99
No errors were found on the image.
100
*** done
101
--
23
--
102
1.8.3.1
24
2.37.3
103
25
104
26
diff view generated by jsdifflib
Deleted patch
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
1
3
- bs->total_sectors is the number of sectors of the whole disk
4
- s->sector_count is the number of sectors of the FAT partition
5
6
This fixes the following assert in qemu-img map:
7
qemu-img.c:2641: get_block_status: Assertion `nb_sectors' failed.
8
9
This also fixes an infinite loop in qemu-img convert.
10
11
Fixes: 4480e0f924a42e1db8b8cfcac4d0634dd1bb27a0
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1599539
13
Cc: qemu-stable@nongnu.org
14
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block/vvfat.c | 3 +--
19
1 file changed, 1 insertion(+), 2 deletions(-)
20
21
diff --git a/block/vvfat.c b/block/vvfat.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/vvfat.c
24
+++ b/block/vvfat.c
25
@@ -XXX,XX +XXX,XX @@ vvfat_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
26
static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs,
27
    int64_t sector_num, int nb_sectors, int *n, BlockDriverState **file)
28
{
29
- BDRVVVFATState* s = bs->opaque;
30
- *n = s->sector_count - sector_num;
31
+ *n = bs->total_sectors - sector_num;
32
if (*n > nb_sectors) {
33
*n = nb_sectors;
34
} else if (*n < 0) {
35
--
36
1.8.3.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
1
3
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
block/vvfat.c | 8 ++++----
7
1 file changed, 4 insertions(+), 4 deletions(-)
8
9
diff --git a/block/vvfat.c b/block/vvfat.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/block/vvfat.c
12
+++ b/block/vvfat.c
13
@@ -XXX,XX +XXX,XX @@ static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
14
/* FAT12/FAT16/FAT32 */
15
/* DOS uses different types when partition is LBA,
16
probably to prevent older versions from using CHS on them */
17
- partition->fs_type= s->fat_type==12 ? 0x1:
18
- s->fat_type==16 ? (lba?0xe:0x06):
19
- /*fat_tyoe==32*/ (lba?0xc:0x0b);
20
+ partition->fs_type = s->fat_type == 12 ? 0x1 :
21
+ s->fat_type == 16 ? (lba ? 0xe : 0x06) :
22
+ /*s->fat_type == 32*/ (lba ? 0xc : 0x0b);
23
24
real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
25
}
26
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
27
(ROOT_ENTRIES - cur) * sizeof(direntry_t));
28
}
29
30
- /* reget the mapping, since s->mapping was possibly realloc()ed */
31
+ /* re-get the mapping, since s->mapping was possibly realloc()ed */
32
mapping = array_get(&(s->mapping), mapping_index);
33
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
34
* 0x20 / s->cluster_size;
35
--
36
1.8.3.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
1
3
Specification: "FAT: General overview of on-disk format" v1.03, pages 11-13
4
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
block/vvfat.c | 21 ++++++++++++++-------
8
1 file changed, 14 insertions(+), 7 deletions(-)
9
10
diff --git a/block/vvfat.c b/block/vvfat.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/vvfat.c
13
+++ b/block/vvfat.c
14
@@ -XXX,XX +XXX,XX @@ typedef struct bootsector_t {
15
union {
16
struct {
17
uint8_t drive_number;
18
- uint8_t current_head;
19
+ uint8_t reserved1;
20
uint8_t signature;
21
uint32_t id;
22
uint8_t volume_label[11];
23
+ uint8_t fat_type[8];
24
+ uint8_t ignored[0x1c0];
25
} QEMU_PACKED fat16;
26
struct {
27
uint32_t sectors_per_fat;
28
uint16_t flags;
29
uint8_t major,minor;
30
- uint32_t first_cluster_of_root_directory;
31
+ uint32_t first_cluster_of_root_dir;
32
uint16_t info_sector;
33
uint16_t backup_boot_sector;
34
- uint16_t ignored;
35
+ uint8_t reserved[12];
36
+ uint8_t drive_number;
37
+ uint8_t reserved1;
38
+ uint8_t signature;
39
+ uint32_t id;
40
+ uint8_t volume_label[11];
41
+ uint8_t fat_type[8];
42
+ uint8_t ignored[0x1a4];
43
} QEMU_PACKED fat32;
44
} u;
45
- uint8_t fat_type[8];
46
- uint8_t ignored[0x1c0];
47
uint8_t magic[2];
48
} QEMU_PACKED bootsector_t;
49
50
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
51
/* LATER TODO: if FAT32, this is wrong */
52
/* drive_number: fda=0, hda=0x80 */
53
bootsector->u.fat16.drive_number = s->offset_to_bootsector == 0 ? 0 : 0x80;
54
- bootsector->u.fat16.current_head=0;
55
bootsector->u.fat16.signature=0x29;
56
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
57
58
memcpy(bootsector->u.fat16.volume_label, s->volume_label,
59
sizeof(bootsector->u.fat16.volume_label));
60
- memcpy(bootsector->fat_type,(s->fat_type==12?"FAT12 ":s->fat_type==16?"FAT16 ":"FAT32 "),8);
61
+ memcpy(bootsector->u.fat16.fat_type,
62
+ s->fat_type == 12 ? "FAT12 " : "FAT16 ", 8);
63
bootsector->magic[0]=0x55; bootsector->magic[1]=0xaa;
64
65
return 0;
66
--
67
1.8.3.1
68
69
diff view generated by jsdifflib
Deleted patch
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
1
3
readdir() doesn't always return . and .. entries at first and in that order.
4
This leads to not creating them at first in the directory, which raises some
5
errors on file system checking utilities like MS-DOS Scandisk.
6
7
Specification: "FAT: General overview of on-disk format" v1.03, page 25
8
9
Fixes: https://bugs.launchpad.net/qemu/+bug/1599539
10
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/vvfat.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/block/vvfat.c b/block/vvfat.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/vvfat.c
19
+++ b/block/vvfat.c
20
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
21
i = mapping->info.dir.first_dir_index =
22
first_cluster == 0 ? 0 : s->directory.next;
23
24
+ if (first_cluster != 0) {
25
+ /* create the top entries of a subdirectory */
26
+ (void)create_short_and_long_name(s, i, ".", 1);
27
+ (void)create_short_and_long_name(s, i, "..", 1);
28
+ }
29
+
30
/* actually read the directory, and allocate the mappings */
31
while((entry=readdir(dir))) {
32
unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
33
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
34
}
35
36
/* create directory entry for this file */
37
- direntry=create_short_and_long_name(s, i, entry->d_name,
38
- is_dot || is_dotdot);
39
+ if (!is_dot && !is_dotdot) {
40
+ direntry = create_short_and_long_name(s, i, entry->d_name, 0);
41
+ } else {
42
+ direntry = array_get(&(s->directory), is_dot ? i : i + 1);
43
+ }
44
direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);
45
direntry->reserved[0]=direntry->reserved[1]=0;
46
direntry->ctime=fat_datetime(st.st_ctime,1);
47
--
48
1.8.3.1
49
50
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
It will be needed in following commits for persistent bitmaps.
3
job mutex will be used to protect the job struct elements and list,
4
If bitmap is loaded from read-only storage (and we can't mark it
4
replacing AioContext locks.
5
"in use" in this storage) corresponding BdrvDirtyBitmap should be
6
read-only.
7
5
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Right now use a shared lock for all jobs, in order to keep things
9
Message-id: 20170628120530.31251-11-vsementsov@virtuozzo.com
7
simple. Once the AioContext lock is gone, we can introduce per-job
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
locks.
9
10
To simplify the switch from aiocontext to job lock, introduce
11
*nop* lock/unlock functions and macros.
12
We want to always call job_lock/unlock outside the AioContext locks,
13
and not vice-versa, otherwise we might get a deadlock. This is not
14
straightforward to do, and that's why we start with nop functions.
15
Once everything is protected by job_lock/unlock, we can change the nop into
16
an actual mutex and remove the aiocontext lock.
17
18
Since job_mutex is already being used, add static
19
real_job_{lock/unlock} for the existing usage.
20
21
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
22
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
23
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
24
Message-Id: <20220926093214.506243-2-eesposit@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
26
---
12
block/dirty-bitmap.c | 36 ++++++++++++++++++++++++++++++++++++
27
include/qemu/job.h | 24 ++++++++++++++++++++++++
13
block/io.c | 8 ++++++++
28
job.c | 35 +++++++++++++++++++++++------------
14
blockdev.c | 6 ++++++
29
2 files changed, 47 insertions(+), 12 deletions(-)
15
include/block/dirty-bitmap.h | 4 ++++
16
4 files changed, 54 insertions(+)
17
30
18
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
31
diff --git a/include/qemu/job.h b/include/qemu/job.h
19
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
20
--- a/block/dirty-bitmap.c
33
--- a/include/qemu/job.h
21
+++ b/block/dirty-bitmap.c
34
+++ b/include/qemu/job.h
22
@@ -XXX,XX +XXX,XX @@ struct BdrvDirtyBitmap {
35
@@ -XXX,XX +XXX,XX @@ typedef enum JobCreateFlags {
23
bool disabled; /* Bitmap is disabled. It ignores all writes to
36
JOB_MANUAL_DISMISS = 0x04,
24
the device */
37
} JobCreateFlags;
25
int active_iterators; /* How many iterators are active */
38
26
+ bool readonly; /* Bitmap is read-only. This field also
39
+extern QemuMutex job_mutex;
27
+ prevents the respective image from being
40
+
28
+ modified (i.e. blocks writes and discards).
41
+#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */
29
+ Such operations must fail and both the image
42
+
30
+ and this bitmap must remain unchanged while
43
+#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */
31
+ this flag is set. */
44
+
32
QLIST_ENTRY(BdrvDirtyBitmap) list;
45
+/**
46
+ * job_lock:
47
+ *
48
+ * Take the mutex protecting the list of jobs and their status.
49
+ * Most functions called by the monitor need to call job_lock
50
+ * and job_unlock manually. On the other hand, function called
51
+ * by the block jobs themselves and by the block layer will take the
52
+ * lock for you.
53
+ */
54
+void job_lock(void);
55
+
56
+/**
57
+ * job_unlock:
58
+ *
59
+ * Release the mutex protecting the list of jobs and their status.
60
+ */
61
+void job_unlock(void);
62
+
63
/**
64
* Allocate and return a new job transaction. Jobs can be added to the
65
* transaction using job_txn_add_job().
66
diff --git a/job.c b/job.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/job.c
69
+++ b/job.c
70
@@ -XXX,XX +XXX,XX @@
71
#include "trace/trace-root.h"
72
#include "qapi/qapi-events-job.h"
73
74
+/*
75
+ * job_mutex protects the jobs list, but also makes the
76
+ * struct job fields thread-safe.
77
+ */
78
+QemuMutex job_mutex;
79
+
80
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
81
82
/* Job State Transition Table */
83
@@ -XXX,XX +XXX,XX @@ struct JobTxn {
84
int refcnt;
33
};
85
};
34
86
35
@@ -XXX,XX +XXX,XX @@ void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
87
-/* Right now, this mutex is only needed to synchronize accesses to job->busy
36
int64_t cur_sector, int64_t nr_sectors)
88
- * and job->sleep_timer, such as concurrent calls to job_do_yield and
37
{
89
- * job_enter. */
38
assert(bdrv_dirty_bitmap_enabled(bitmap));
90
-static QemuMutex job_mutex;
39
+ assert(!bdrv_dirty_bitmap_readonly(bitmap));
91
+void job_lock(void)
40
hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
41
}
42
43
@@ -XXX,XX +XXX,XX @@ void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap,
44
int64_t cur_sector, int64_t nr_sectors)
45
{
46
assert(bdrv_dirty_bitmap_enabled(bitmap));
47
+ assert(!bdrv_dirty_bitmap_readonly(bitmap));
48
hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
49
}
50
51
@@ -XXX,XX +XXX,XX @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
52
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
53
{
54
assert(bdrv_dirty_bitmap_enabled(bitmap));
55
+ assert(!bdrv_dirty_bitmap_readonly(bitmap));
56
bdrv_dirty_bitmap_lock(bitmap);
57
if (!out) {
58
hbitmap_reset_all(bitmap->bitmap);
59
@@ -XXX,XX +XXX,XX @@ void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
60
{
61
HBitmap *tmp = bitmap->bitmap;
62
assert(bdrv_dirty_bitmap_enabled(bitmap));
63
+ assert(!bdrv_dirty_bitmap_readonly(bitmap));
64
bitmap->bitmap = in;
65
hbitmap_free(tmp);
66
}
67
@@ -XXX,XX +XXX,XX @@ void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
68
if (!bdrv_dirty_bitmap_enabled(bitmap)) {
69
continue;
70
}
71
+ assert(!bdrv_dirty_bitmap_readonly(bitmap));
72
hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors);
73
}
74
bdrv_dirty_bitmaps_unlock(bs);
75
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap)
76
{
77
return hbitmap_count(bitmap->meta);
78
}
79
+
80
+bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap)
81
+{
92
+{
82
+ return bitmap->readonly;
93
+ /* nop */
83
+}
94
+}
84
+
95
+
85
+/* Called with BQL taken. */
96
+void job_unlock(void)
86
+void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value)
87
+{
97
+{
88
+ qemu_mutex_lock(bitmap->mutex);
98
+ /* nop */
89
+ bitmap->readonly = value;
90
+ qemu_mutex_unlock(bitmap->mutex);
91
+}
99
+}
92
+
100
93
+bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
101
-static void job_lock(void)
94
+{
102
+static void real_job_lock(void)
95
+ BdrvDirtyBitmap *bm;
103
{
96
+ QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
104
qemu_mutex_lock(&job_mutex);
97
+ if (bm->readonly) {
105
}
98
+ return true;
106
99
+ }
107
-static void job_unlock(void)
100
+ }
108
+static void real_job_unlock(void)
101
+
109
{
102
+ return false;
110
qemu_mutex_unlock(&job_mutex);
103
+}
111
}
104
diff --git a/block/io.c b/block/io.c
112
@@ -XXX,XX +XXX,XX @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
105
index XXXXXXX..XXXXXXX 100644
113
return;
106
--- a/block/io.c
107
+++ b/block/io.c
108
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
109
uint64_t bytes_remaining = bytes;
110
int max_transfer;
111
112
+ if (bdrv_has_readonly_bitmaps(bs)) {
113
+ return -EPERM;
114
+ }
115
+
116
assert(is_power_of_2(align));
117
assert((offset & (align - 1)) == 0);
118
assert((bytes & (align - 1)) == 0);
119
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
120
return -ENOMEDIUM;
121
}
114
}
122
115
123
+ if (bdrv_has_readonly_bitmaps(bs)) {
116
- job_lock();
124
+ return -EPERM;
117
+ real_job_lock();
125
+ }
118
if (job->busy) {
126
+
119
- job_unlock();
127
ret = bdrv_check_byte_request(bs, offset, bytes);
120
+ real_job_unlock();
128
if (ret < 0) {
129
return ret;
130
diff --git a/blockdev.c b/blockdev.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/blockdev.c
133
+++ b/blockdev.c
134
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
135
} else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
136
error_setg(errp, "Cannot clear a disabled bitmap");
137
return;
121
return;
138
+ } else if (bdrv_dirty_bitmap_readonly(state->bitmap)) {
139
+ error_setg(errp, "Cannot clear a readonly bitmap");
140
+ return;
141
}
122
}
142
123
143
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
124
if (fn && !fn(job)) {
144
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
125
- job_unlock();
145
"Bitmap '%s' is currently disabled and cannot be cleared",
126
+ real_job_unlock();
146
name);
147
return;
127
return;
148
+ } else if (bdrv_dirty_bitmap_readonly(bitmap)) {
149
+ error_setg(errp, "Bitmap '%s' is readonly and cannot be cleared", name);
150
+ return;
151
}
128
}
152
129
153
bdrv_clear_dirty_bitmap(bitmap, NULL);
130
assert(!job->deferred_to_main_loop);
154
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
131
timer_del(&job->sleep_timer);
155
index XXXXXXX..XXXXXXX 100644
132
job->busy = true;
156
--- a/include/block/dirty-bitmap.h
133
- job_unlock();
157
+++ b/include/block/dirty-bitmap.h
134
+ real_job_unlock();
158
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
135
aio_co_enter(job->aio_context, job->co);
159
bool finish);
136
}
160
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
137
161
138
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
162
+void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
139
* called explicitly. */
163
+
140
static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
164
/* Functions that require manual locking. */
141
{
165
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
142
- job_lock();
166
void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap);
143
+ real_job_lock();
167
@@ -XXX,XX +XXX,XX @@ void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *hbi, int64_t sector_num);
144
if (ns != -1) {
168
int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap);
145
timer_mod(&job->sleep_timer, ns);
169
int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap);
146
}
170
void bdrv_dirty_bitmap_truncate(BlockDriverState *bs);
147
job->busy = false;
171
+bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
148
job_event_idle(job);
172
+bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
149
- job_unlock();
173
150
+ real_job_unlock();
174
#endif
151
qemu_coroutine_yield();
152
153
/* Set by job_enter_cond() before re-entering the coroutine. */
175
--
154
--
176
1.8.3.1
155
2.37.3
177
178
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Assume that input filename is encoded as UTF-8, so correctly create UTF-16 encoding.
3
Categorize the fields in struct Job to understand which ones
4
need to be protected by the job mutex and which don't.
4
5
5
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20220926093214.506243-3-eesposit@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
12
---
8
block/vvfat.c | 38 ++++++++++++++++++--------------------
13
include/qemu/job.h | 61 +++++++++++++++++++++++++++-------------------
9
1 file changed, 18 insertions(+), 20 deletions(-)
14
1 file changed, 36 insertions(+), 25 deletions(-)
10
15
11
diff --git a/block/vvfat.c b/block/vvfat.c
16
diff --git a/include/qemu/job.h b/include/qemu/job.h
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/block/vvfat.c
18
--- a/include/qemu/job.h
14
+++ b/block/vvfat.c
19
+++ b/include/qemu/job.h
15
@@ -XXX,XX +XXX,XX @@ static void init_mbr(BDRVVVFATState *s, int cyls, int heads, int secs)
20
@@ -XXX,XX +XXX,XX @@ typedef struct JobTxn JobTxn;
16
21
* Long-running operation.
17
/* direntry functions */
22
*/
18
23
typedef struct Job {
19
-/* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */
20
-static inline int short2long_name(char* dest,const char* src)
21
+static direntry_t *create_long_filename(BDRVVVFATState *s, const char *filename)
22
{
23
- int i;
24
- int len;
25
- for(i=0;i<129 && src[i];i++) {
26
- dest[2*i]=src[i];
27
- dest[2*i+1]=0;
28
+ int number_of_entries, i;
29
+ glong length;
30
+ direntry_t *entry;
31
+
24
+
32
+ gunichar2 *longname = g_utf8_to_utf16(filename, -1, NULL, &length, NULL);
25
+ /* Fields set at initialization (job_create), and never modified */
33
+ if (!longname) {
26
+
34
+ fprintf(stderr, "vvfat: invalid UTF-8 name: %s\n", filename);
27
/** The ID of the job. May be NULL for internal jobs. */
35
+ return NULL;
28
char *id;
36
}
29
37
- len=2*i;
30
- /** The type of this job. */
38
- dest[2*i]=dest[2*i+1]=0;
31
+ /**
39
- for(i=2*i+2;(i%26);i++)
32
+ * The type of this job.
40
- dest[i]=0xff;
33
+ * All callbacks are called with job_mutex *not* held.
41
- return len;
34
+ */
42
-}
35
const JobDriver *driver;
43
36
44
-static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
37
- /** Reference count of the block job */
45
-{
38
- int refcnt;
46
- char buffer[258];
39
-
47
- int length=short2long_name(buffer,filename),
40
- /** Current state; See @JobStatus for details. */
48
- number_of_entries=(length+25)/26,i;
41
- JobStatus status;
49
- direntry_t* entry;
42
-
50
+ number_of_entries = (length * 2 + 25) / 26;
43
- /** AioContext to run the job coroutine in */
51
44
- AioContext *aio_context;
52
for(i=0;i<number_of_entries;i++) {
45
-
53
entry=array_get_next(&(s->directory));
46
/**
54
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* fil
47
* The coroutine that executes the job. If not NULL, it is reentered when
55
else if(offset<22) offset=14+offset-10;
48
* busy is false and the job is cancelled.
56
else offset=28+offset-22;
49
+ * Initialized in job_start()
57
entry=array_get(&(s->directory),s->directory.next-1-(i/26));
50
*/
58
- entry->name[offset]=buffer[i];
51
Coroutine *co;
59
+ if (i >= 2 * length + 2) {
52
60
+ entry->name[offset] = 0xff;
53
+ /** True if this job should automatically finalize itself */
61
+ } else if (i % 2 == 0) {
54
+ bool auto_finalize;
62
+ entry->name[offset] = longname[i / 2] & 0xff;
55
+
63
+ } else {
56
+ /** True if this job should automatically dismiss itself */
64
+ entry->name[offset] = longname[i / 2] >> 8;
57
+ bool auto_dismiss;
65
+ }
58
+
66
}
59
+ /** The completion function that will be called when the job completes. */
67
+ g_free(longname);
60
+ BlockCompletionFunc *cb;
68
return array_get(&(s->directory),s->directory.next-number_of_entries);
61
+
69
}
62
+ /** The opaque value that is passed to the completion function. */
63
+ void *opaque;
64
+
65
+ /* ProgressMeter API is thread-safe */
66
+ ProgressMeter progress;
67
+
68
+
69
+ /** Protected by AioContext lock */
70
+
71
+ /** AioContext to run the job coroutine in */
72
+ AioContext *aio_context;
73
+
74
+ /** Reference count of the block job */
75
+ int refcnt;
76
+
77
+ /** Current state; See @JobStatus for details. */
78
+ JobStatus status;
79
+
80
/**
81
* Timer that is used by @job_sleep_ns. Accessed under job_mutex (in
82
* job.c).
83
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
84
/** Set to true when the job has deferred work to the main loop. */
85
bool deferred_to_main_loop;
86
87
- /** True if this job should automatically finalize itself */
88
- bool auto_finalize;
89
-
90
- /** True if this job should automatically dismiss itself */
91
- bool auto_dismiss;
92
-
93
- ProgressMeter progress;
94
-
95
/**
96
* Return code from @run and/or @prepare callback(s).
97
* Not final until the job has reached the CONCLUDED status.
98
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
99
*/
100
Error *err;
101
102
- /** The completion function that will be called when the job completes. */
103
- BlockCompletionFunc *cb;
104
-
105
- /** The opaque value that is passed to the completion function. */
106
- void *opaque;
107
-
108
/** Notifiers called when a cancelled job is finalised */
109
NotifierList on_finalize_cancelled;
110
111
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
112
113
/**
114
* Callbacks and other information about a Job driver.
115
+ * All callbacks are invoked with job_mutex *not* held.
116
*/
117
struct JobDriver {
118
119
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_yield(Job *job);
120
*/
121
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
122
123
-
124
/** Returns the JobType of a given Job. */
125
JobType job_type(const Job *job);
70
126
71
--
127
--
72
1.8.3.1
128
2.37.3
73
74
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
job_event_* functions can all be static, as they are not used
4
byte-based. In the common case, allocation is unlikely to ever use
4
outside job.c.
5
values that are not naturally sector-aligned, but it is possible
6
that byte-based values will let us be more precise about allocation
7
at the end of an unaligned file that can do byte-based access.
8
5
9
Changing the signature of the function to use int64_t *pnum ensures
6
Same applies for job_txn_add_job().
10
that the compiler enforces that all callers are updated. For now,
11
the io.c layer still assert()s that all callers are sector-aligned
12
on input and that *pnum is sector-aligned on return to the caller,
13
but that can be relaxed when a later patch implements byte-based
14
block status. Therefore, this code adds usages like
15
DIV_ROUND_UP(,BDRV_SECTOR_SIZE) to callers that still want aligned
16
values, where the call might reasonbly give non-aligned results
17
in the future; on the other hand, no rounding is needed for callers
18
that should just continue to work with byte alignment.
19
7
20
For the most part this patch is just the addition of scaling at the
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
21
callers followed by inverse scaling at bdrv_is_allocated(). But
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
some code, particularly bdrv_commit(), gets a lot simpler because it
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
23
no longer has to mess with sectors; also, it is now possible to pass
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
24
NULL if the caller does not care how much of the image is allocated
12
Message-Id: <20220926093214.506243-4-eesposit@redhat.com>
25
beyond the initial offset. Leave comments where we can further
26
simplify once a later patch eliminates the need for sector-aligned
27
requests through bdrv_is_allocated().
28
29
For ease of review, bdrv_is_allocated_above() will be tackled
30
separately.
31
32
Signed-off-by: Eric Blake <eblake@redhat.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
14
---
35
block/backup.c | 17 ++++---------
15
include/qemu/job.h | 18 ------------------
36
block/commit.c | 21 +++++++---------
16
job.c | 22 +++++++++++++++++++---
37
block/io.c | 54 ++++++++++++++++++++++++++-------------
17
2 files changed, 19 insertions(+), 21 deletions(-)
38
block/stream.c | 7 ++++--
39
block/vvfat.c | 34 ++++++++++++++-----------
40
include/block/block.h | 4 +--
41
migration/block.c | 16 +++++++-----
42
qemu-img.c | 8 +++++-
43
qemu-io-cmds.c | 70 +++++++++++++++++++++++----------------------------
44
9 files changed, 126 insertions(+), 105 deletions(-)
45
18
46
diff --git a/block/backup.c b/block/backup.c
19
diff --git a/include/qemu/job.h b/include/qemu/job.h
47
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
48
--- a/block/backup.c
21
--- a/include/qemu/job.h
49
+++ b/block/backup.c
22
+++ b/include/qemu/job.h
50
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
23
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
51
QLIST_HEAD(, CowRequest) inflight_reqs;
24
*/
52
} BackupBlockJob;
25
void job_txn_unref(JobTxn *txn);
53
26
54
-/* Size of a cluster in sectors, instead of bytes. */
27
-/**
55
-static inline int64_t cluster_size_sectors(BackupBlockJob *job)
28
- * @txn: The transaction (may be NULL)
56
-{
29
- * @job: Job to add to the transaction
57
- return job->cluster_size / BDRV_SECTOR_SIZE;
30
- *
58
-}
31
- * Add @job to the transaction. The @job must not already be in a transaction.
32
- * The caller must call either job_txn_unref() or job_completed() to release
33
- * the reference that is automatically grabbed here.
34
- *
35
- * If @txn is NULL, the function does nothing.
36
- */
37
-void job_txn_add_job(JobTxn *txn, Job *job);
59
-
38
-
60
/* See if in-flight requests overlap and wait for them to complete */
39
/**
61
static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
40
* Create a new long-running job and return it.
62
int64_t start,
41
*
63
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
42
@@ -XXX,XX +XXX,XX @@ void job_progress_set_remaining(Job *job, uint64_t remaining);
64
BackupCompleteData *data;
43
*/
65
BlockDriverState *bs = blk_bs(job->common.blk);
44
void job_progress_increase_remaining(Job *job, uint64_t delta);
66
int64_t offset;
45
67
- int64_t sectors_per_cluster = cluster_size_sectors(job);
46
-/** To be called when a cancelled job is finalised. */
68
int ret = 0;
47
-void job_event_cancelled(Job *job);
69
48
-
70
QLIST_INIT(&job->inflight_reqs);
49
-/** To be called when a successfully completed job is finalised. */
71
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
50
-void job_event_completed(Job *job);
72
}
51
-
73
52
/**
74
if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
53
* Conditionally enter the job coroutine if the job is ready to run, not
75
- int i, n;
54
* already busy and fn() returns true. fn() is called while under the job_lock
76
+ int i;
55
diff --git a/job.c b/job.c
77
+ int64_t n;
78
79
/* Check to see if these blocks are already in the
80
* backing file. */
81
82
- for (i = 0; i < sectors_per_cluster;) {
83
+ for (i = 0; i < job->cluster_size;) {
84
/* bdrv_is_allocated() only returns true/false based
85
* on the first set of sectors it comes across that
86
* are are all in the same state.
87
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
88
* backup cluster length. We end up copying more than
89
* needed but at some point that is always the case. */
90
alloced =
91
- bdrv_is_allocated(bs,
92
- (offset >> BDRV_SECTOR_BITS) + i,
93
- sectors_per_cluster - i, &n);
94
+ bdrv_is_allocated(bs, offset + i,
95
+ job->cluster_size - i, &n);
96
i += n;
97
98
if (alloced || n == 0) {
99
diff --git a/block/commit.c b/block/commit.c
100
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
101
--- a/block/commit.c
57
--- a/job.c
102
+++ b/block/commit.c
58
+++ b/job.c
103
@@ -XXX,XX +XXX,XX @@ fail:
59
@@ -XXX,XX +XXX,XX @@ void job_txn_unref(JobTxn *txn)
60
}
104
}
61
}
105
62
106
63
-void job_txn_add_job(JobTxn *txn, Job *job)
107
-#define COMMIT_BUF_SECTORS 2048
64
+/**
108
+#define COMMIT_BUF_SIZE (2048 * BDRV_SECTOR_SIZE)
65
+ * @txn: The transaction (may be NULL)
109
66
+ * @job: Job to add to the transaction
110
/* commit COW file into the raw image */
67
+ *
111
int bdrv_commit(BlockDriverState *bs)
68
+ * Add @job to the transaction. The @job must not already be in a transaction.
112
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
69
+ * The caller must call either job_txn_unref() or job_completed() to release
113
BlockDriverState *backing_file_bs = NULL;
70
+ * the reference that is automatically grabbed here.
114
BlockDriverState *commit_top_bs = NULL;
71
+ *
115
BlockDriver *drv = bs->drv;
72
+ * If @txn is NULL, the function does nothing.
116
- int64_t sector, total_sectors, length, backing_length;
73
+ */
117
- int n, ro, open_flags;
74
+static void job_txn_add_job(JobTxn *txn, Job *job)
118
+ int64_t offset, length, backing_length;
75
{
119
+ int ro, open_flags;
76
if (!txn) {
120
+ int64_t n;
77
return;
121
int ret = 0;
78
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta)
122
uint8_t *buf = NULL;
79
progress_increase_remaining(&job->progress, delta);
123
Error *local_err = NULL;
124
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
125
}
126
}
127
128
- total_sectors = length >> BDRV_SECTOR_BITS;
129
-
130
/* blk_try_blockalign() for src will choose an alignment that works for
131
* backing as well, so no need to compare the alignment manually. */
132
- buf = blk_try_blockalign(src, COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
133
+ buf = blk_try_blockalign(src, COMMIT_BUF_SIZE);
134
if (buf == NULL) {
135
ret = -ENOMEM;
136
goto ro_cleanup;
137
}
138
139
- for (sector = 0; sector < total_sectors; sector += n) {
140
- ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
141
+ for (offset = 0; offset < length; offset += n) {
142
+ ret = bdrv_is_allocated(bs, offset, COMMIT_BUF_SIZE, &n);
143
if (ret < 0) {
144
goto ro_cleanup;
145
}
146
if (ret) {
147
- ret = blk_pread(src, sector * BDRV_SECTOR_SIZE, buf,
148
- n * BDRV_SECTOR_SIZE);
149
+ ret = blk_pread(src, offset, buf, n);
150
if (ret < 0) {
151
goto ro_cleanup;
152
}
153
154
- ret = blk_pwrite(backing, sector * BDRV_SECTOR_SIZE, buf,
155
- n * BDRV_SECTOR_SIZE, 0);
156
+ ret = blk_pwrite(backing, offset, buf, n, 0);
157
if (ret < 0) {
158
goto ro_cleanup;
159
}
160
diff --git a/block/io.c b/block/io.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/io.c
163
+++ b/block/io.c
164
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
165
}
166
167
if (flags & BDRV_REQ_COPY_ON_READ) {
168
- int64_t start_sector = offset >> BDRV_SECTOR_BITS;
169
- int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
170
- unsigned int nb_sectors = end_sector - start_sector;
171
- int pnum;
172
+ /* TODO: Simplify further once bdrv_is_allocated no longer
173
+ * requires sector alignment */
174
+ int64_t start = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
175
+ int64_t end = QEMU_ALIGN_UP(offset + bytes, BDRV_SECTOR_SIZE);
176
+ int64_t pnum;
177
178
- ret = bdrv_is_allocated(bs, start_sector, nb_sectors, &pnum);
179
+ ret = bdrv_is_allocated(bs, start, end - start, &pnum);
180
if (ret < 0) {
181
goto out;
182
}
183
184
- if (!ret || pnum != nb_sectors) {
185
+ if (!ret || pnum != end - start) {
186
ret = bdrv_co_do_copy_on_readv(child, offset, bytes, qiov);
187
goto out;
188
}
189
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status(BlockDriverState *bs,
190
sector_num, nb_sectors, pnum, file);
191
}
80
}
192
81
193
-int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
82
-void job_event_cancelled(Job *job)
194
- int nb_sectors, int *pnum)
83
+/**
195
+int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
84
+ * To be called when a cancelled job is finalised.
196
+ int64_t bytes, int64_t *pnum)
85
+ */
86
+static void job_event_cancelled(Job *job)
197
{
87
{
198
BlockDriverState *file;
88
notifier_list_notify(&job->on_finalize_cancelled, job);
199
- int64_t ret = bdrv_get_block_status(bs, sector_num, nb_sectors, pnum,
200
- &file);
201
+ int64_t sector_num = offset >> BDRV_SECTOR_BITS;
202
+ int nb_sectors = bytes >> BDRV_SECTOR_BITS;
203
+ int64_t ret;
204
+ int psectors;
205
+
206
+ assert(QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE));
207
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE) && bytes < INT_MAX);
208
+ ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &psectors,
209
+ &file);
210
if (ret < 0) {
211
return ret;
212
}
213
+ if (pnum) {
214
+ *pnum = psectors * BDRV_SECTOR_SIZE;
215
+ }
216
return !!(ret & BDRV_BLOCK_ALLOCATED);
217
}
89
}
218
90
219
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num,
91
-void job_event_completed(Job *job)
220
*
92
+/**
221
* Return true if the given sector is allocated in any image between
93
+ * To be called when a successfully completed job is finalised.
222
* BASE and TOP (inclusive). BASE can be NULL to check if the given
94
+ */
223
- * sector is allocated in any image of the chain. Return false otherwise.
95
+static void job_event_completed(Job *job)
224
+ * sector is allocated in any image of the chain. Return false otherwise,
225
+ * or negative errno on failure.
226
*
227
* 'pnum' is set to the number of sectors (including and immediately following
228
* the specified sector) that are known to be in the same
229
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top,
230
231
intermediate = top;
232
while (intermediate && intermediate != base) {
233
- int pnum_inter;
234
- ret = bdrv_is_allocated(intermediate, sector_num, nb_sectors,
235
+ int64_t pnum_inter;
236
+ int psectors_inter;
237
+
238
+ ret = bdrv_is_allocated(intermediate, sector_num * BDRV_SECTOR_SIZE,
239
+ nb_sectors * BDRV_SECTOR_SIZE,
240
&pnum_inter);
241
if (ret < 0) {
242
return ret;
243
- } else if (ret) {
244
- *pnum = pnum_inter;
245
+ }
246
+ assert(pnum_inter < INT_MAX * BDRV_SECTOR_SIZE);
247
+ psectors_inter = pnum_inter >> BDRV_SECTOR_BITS;
248
+ if (ret) {
249
+ *pnum = psectors_inter;
250
return 1;
251
}
252
253
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top,
254
*
255
* [sector_num+x, nr_sectors] allocated.
256
*/
257
- if (n > pnum_inter &&
258
+ if (n > psectors_inter &&
259
(intermediate == top ||
260
- sector_num + pnum_inter < intermediate->total_sectors)) {
261
- n = pnum_inter;
262
+ sector_num + psectors_inter < intermediate->total_sectors)) {
263
+ n = psectors_inter;
264
}
265
266
intermediate = backing_bs(intermediate);
267
diff --git a/block/stream.c b/block/stream.c
268
index XXXXXXX..XXXXXXX 100644
269
--- a/block/stream.c
270
+++ b/block/stream.c
271
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
272
273
for ( ; offset < s->common.len; offset += n * BDRV_SECTOR_SIZE) {
274
bool copy;
275
+ int64_t count = 0;
276
277
/* Note that even when no rate limit is applied we need to yield
278
* with no pending I/O here so that bdrv_drain_all() returns.
279
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
280
281
copy = false;
282
283
- ret = bdrv_is_allocated(bs, offset / BDRV_SECTOR_SIZE,
284
- STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
285
+ ret = bdrv_is_allocated(bs, offset, STREAM_BUFFER_SIZE, &count);
286
+ /* TODO relax this once bdrv_is_allocated does not enforce sectors */
287
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
288
+ n = count >> BDRV_SECTOR_BITS;
289
if (ret == 1) {
290
/* Allocated in the top, no need to copy. */
291
} else if (ret >= 0) {
292
diff --git a/block/vvfat.c b/block/vvfat.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/block/vvfat.c
295
+++ b/block/vvfat.c
296
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
297
if (sector_num >= bs->total_sectors)
298
return -1;
299
if (s->qcow) {
300
- int n;
301
+ int64_t n;
302
int ret;
303
- ret = bdrv_is_allocated(s->qcow->bs, sector_num,
304
- nb_sectors - i, &n);
305
+ ret = bdrv_is_allocated(s->qcow->bs, sector_num * BDRV_SECTOR_SIZE,
306
+ (nb_sectors - i) * BDRV_SECTOR_SIZE, &n);
307
if (ret < 0) {
308
return ret;
309
}
310
if (ret) {
311
- DLOG(fprintf(stderr, "sectors %d+%d allocated\n",
312
- (int)sector_num, n));
313
- if (bdrv_read(s->qcow, sector_num, buf + i * 0x200, n)) {
314
+ DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
315
+ " allocated\n", sector_num,
316
+ n >> BDRV_SECTOR_BITS));
317
+ if (bdrv_read(s->qcow, sector_num, buf + i * 0x200,
318
+ n >> BDRV_SECTOR_BITS)) {
319
return -1;
320
}
321
- i += n - 1;
322
- sector_num += n - 1;
323
+ i += (n >> BDRV_SECTOR_BITS) - 1;
324
+ sector_num += (n >> BDRV_SECTOR_BITS) - 1;
325
continue;
326
}
327
-DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
328
+ DLOG(fprintf(stderr, "sector %" PRId64 " not allocated\n",
329
+ sector_num));
330
}
331
if (sector_num < s->offset_to_root_dir) {
332
if (sector_num < s->offset_to_fat) {
333
@@ -XXX,XX +XXX,XX @@ static inline bool cluster_was_modified(BDRVVVFATState *s,
334
uint32_t cluster_num)
335
{
96
{
336
int was_modified = 0;
97
notifier_list_notify(&job->on_finalize_completed, job);
337
- int i, dummy;
338
+ int i;
339
340
if (s->qcow == NULL) {
341
return 0;
342
@@ -XXX,XX +XXX,XX @@ static inline bool cluster_was_modified(BDRVVVFATState *s,
343
344
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++) {
345
was_modified = bdrv_is_allocated(s->qcow->bs,
346
- cluster2sector(s, cluster_num) + i,
347
- 1, &dummy);
348
+ (cluster2sector(s, cluster_num) +
349
+ i) * BDRV_SECTOR_SIZE,
350
+ BDRV_SECTOR_SIZE, NULL);
351
}
352
353
/*
354
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
355
}
356
357
if (copy_it) {
358
- int i, dummy;
359
+ int i;
360
/*
361
* This is horribly inefficient, but that is okay, since
362
* it is rarely executed, if at all.
363
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
364
for (i = 0; i < s->sectors_per_cluster; i++) {
365
int res;
366
367
- res = bdrv_is_allocated(s->qcow->bs, offset + i, 1, &dummy);
368
+ res = bdrv_is_allocated(s->qcow->bs,
369
+ (offset + i) * BDRV_SECTOR_SIZE,
370
+ BDRV_SECTOR_SIZE, NULL);
371
if (res < 0) {
372
return -1;
373
}
374
diff --git a/include/block/block.h b/include/block/block.h
375
index XXXXXXX..XXXXXXX 100644
376
--- a/include/block/block.h
377
+++ b/include/block/block.h
378
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
379
int64_t sector_num,
380
int nb_sectors, int *pnum,
381
BlockDriverState **file);
382
-int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
383
- int *pnum);
384
+int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
385
+ int64_t *pnum);
386
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
387
int64_t sector_num, int nb_sectors, int *pnum);
388
389
diff --git a/migration/block.c b/migration/block.c
390
index XXXXXXX..XXXXXXX 100644
391
--- a/migration/block.c
392
+++ b/migration/block.c
393
@@ -XXX,XX +XXX,XX @@
394
#define BLK_MIG_FLAG_PROGRESS 0x04
395
#define BLK_MIG_FLAG_ZERO_BLOCK 0x08
396
397
-#define MAX_IS_ALLOCATED_SEARCH 65536
398
+#define MAX_IS_ALLOCATED_SEARCH (65536 * BDRV_SECTOR_SIZE)
399
400
#define MAX_INFLIGHT_IO 512
401
402
@@ -XXX,XX +XXX,XX @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
403
BlockBackend *bb = bmds->blk;
404
BlkMigBlock *blk;
405
int nr_sectors;
406
+ int64_t count;
407
408
if (bmds->shared_base) {
409
qemu_mutex_lock_iothread();
410
aio_context_acquire(blk_get_aio_context(bb));
411
- /* Skip unallocated sectors; intentionally treats failure as
412
- * an allocated sector */
413
+ /* Skip unallocated sectors; intentionally treats failure or
414
+ * partial sector as an allocated sector */
415
while (cur_sector < total_sectors &&
416
- !bdrv_is_allocated(blk_bs(bb), cur_sector,
417
- MAX_IS_ALLOCATED_SEARCH, &nr_sectors)) {
418
- cur_sector += nr_sectors;
419
+ !bdrv_is_allocated(blk_bs(bb), cur_sector * BDRV_SECTOR_SIZE,
420
+ MAX_IS_ALLOCATED_SEARCH, &count)) {
421
+ if (count < BDRV_SECTOR_SIZE) {
422
+ break;
423
+ }
424
+ cur_sector += count >> BDRV_SECTOR_BITS;
425
}
426
aio_context_release(blk_get_aio_context(bb));
427
qemu_mutex_unlock_iothread();
428
diff --git a/qemu-img.c b/qemu-img.c
429
index XXXXXXX..XXXXXXX 100644
430
--- a/qemu-img.c
431
+++ b/qemu-img.c
432
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
433
int64_t new_backing_num_sectors = 0;
434
uint64_t sector;
435
int n;
436
+ int64_t count;
437
float local_progress = 0;
438
439
buf_old = blk_blockalign(blk, IO_BUF_SIZE);
440
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
441
}
442
443
/* If the cluster is allocated, we don't need to take action */
444
- ret = bdrv_is_allocated(bs, sector, n, &n);
445
+ ret = bdrv_is_allocated(bs, sector << BDRV_SECTOR_BITS,
446
+ n << BDRV_SECTOR_BITS, &count);
447
if (ret < 0) {
448
error_report("error while reading image metadata: %s",
449
strerror(-ret));
450
goto out;
451
}
452
+ /* TODO relax this once bdrv_is_allocated does not enforce
453
+ * sector alignment */
454
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
455
+ n = count >> BDRV_SECTOR_BITS;
456
if (ret) {
457
continue;
458
}
459
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/qemu-io-cmds.c
462
+++ b/qemu-io-cmds.c
463
@@ -XXX,XX +XXX,XX @@ out:
464
static int alloc_f(BlockBackend *blk, int argc, char **argv)
465
{
466
BlockDriverState *bs = blk_bs(blk);
467
- int64_t offset, sector_num, nb_sectors, remaining, count;
468
+ int64_t offset, start, remaining, count;
469
char s1[64];
470
- int num, ret;
471
- int64_t sum_alloc;
472
+ int ret;
473
+ int64_t num, sum_alloc;
474
475
- offset = cvtnum(argv[1]);
476
+ start = offset = cvtnum(argv[1]);
477
if (offset < 0) {
478
print_cvtnum_err(offset, argv[1]);
479
return 0;
480
@@ -XXX,XX +XXX,XX @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
481
count);
482
return 0;
483
}
484
- nb_sectors = count >> BDRV_SECTOR_BITS;
485
486
- remaining = nb_sectors;
487
+ remaining = count;
488
sum_alloc = 0;
489
- sector_num = offset >> 9;
490
while (remaining) {
491
- ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
492
+ ret = bdrv_is_allocated(bs, offset, remaining, &num);
493
if (ret < 0) {
494
printf("is_allocated failed: %s\n", strerror(-ret));
495
return 0;
496
}
497
- sector_num += num;
498
+ offset += num;
499
remaining -= num;
500
if (ret) {
501
sum_alloc += num;
502
}
503
if (num == 0) {
504
- nb_sectors -= remaining;
505
+ count -= remaining;
506
remaining = 0;
507
}
508
}
509
510
- cvtstr(offset, s1, sizeof(s1));
511
+ cvtstr(start, s1, sizeof(s1));
512
513
printf("%"PRId64"/%"PRId64" bytes allocated at offset %s\n",
514
- sum_alloc << BDRV_SECTOR_BITS, nb_sectors << BDRV_SECTOR_BITS, s1);
515
+ sum_alloc, count, s1);
516
return 0;
517
}
518
519
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t alloc_cmd = {
520
};
521
522
523
-static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
524
- int64_t nb_sectors, int64_t *pnum)
525
+static int map_is_allocated(BlockDriverState *bs, int64_t offset,
526
+ int64_t bytes, int64_t *pnum)
527
{
528
- int num, num_checked;
529
+ int64_t num;
530
+ int num_checked;
531
int ret, firstret;
532
533
- num_checked = MIN(nb_sectors, INT_MAX);
534
- ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
535
+ num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
536
+ ret = bdrv_is_allocated(bs, offset, num_checked, &num);
537
if (ret < 0) {
538
return ret;
539
}
540
@@ -XXX,XX +XXX,XX @@ static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
541
firstret = ret;
542
*pnum = num;
543
544
- while (nb_sectors > 0 && ret == firstret) {
545
- sector_num += num;
546
- nb_sectors -= num;
547
+ while (bytes > 0 && ret == firstret) {
548
+ offset += num;
549
+ bytes -= num;
550
551
- num_checked = MIN(nb_sectors, INT_MAX);
552
- ret = bdrv_is_allocated(bs, sector_num, num_checked, &num);
553
+ num_checked = MIN(bytes, BDRV_REQUEST_MAX_BYTES);
554
+ ret = bdrv_is_allocated(bs, offset, num_checked, &num);
555
if (ret == firstret && num) {
556
*pnum += num;
557
} else {
558
@@ -XXX,XX +XXX,XX @@ static int map_is_allocated(BlockDriverState *bs, int64_t sector_num,
559
560
static int map_f(BlockBackend *blk, int argc, char **argv)
561
{
562
- int64_t offset;
563
- int64_t nb_sectors, total_sectors;
564
+ int64_t offset, bytes;
565
char s1[64], s2[64];
566
int64_t num;
567
int ret;
568
const char *retstr;
569
570
offset = 0;
571
- total_sectors = blk_nb_sectors(blk);
572
- if (total_sectors < 0) {
573
- error_report("Failed to query image length: %s",
574
- strerror(-total_sectors));
575
+ bytes = blk_getlength(blk);
576
+ if (bytes < 0) {
577
+ error_report("Failed to query image length: %s", strerror(-bytes));
578
return 0;
579
}
580
581
- nb_sectors = total_sectors;
582
-
583
- do {
584
- ret = map_is_allocated(blk_bs(blk), offset, nb_sectors, &num);
585
+ while (bytes) {
586
+ ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
587
if (ret < 0) {
588
error_report("Failed to get allocation status: %s", strerror(-ret));
589
return 0;
590
@@ -XXX,XX +XXX,XX @@ static int map_f(BlockBackend *blk, int argc, char **argv)
591
}
592
593
retstr = ret ? " allocated" : "not allocated";
594
- cvtstr(num << BDRV_SECTOR_BITS, s1, sizeof(s1));
595
- cvtstr(offset << BDRV_SECTOR_BITS, s2, sizeof(s2));
596
+ cvtstr(num, s1, sizeof(s1));
597
+ cvtstr(offset, s2, sizeof(s2));
598
printf("%s (0x%" PRIx64 ") bytes %s at offset %s (0x%" PRIx64 ")\n",
599
- s1, num << BDRV_SECTOR_BITS, retstr,
600
- s2, offset << BDRV_SECTOR_BITS);
601
+ s1, num, retstr, s2, offset);
602
603
offset += num;
604
- nb_sectors -= num;
605
- } while (offset < total_sectors);
606
+ bytes -= num;
607
+ }
608
609
return 0;
610
}
98
}
611
--
99
--
612
1.8.3.1
100
2.37.3
613
614
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Same as AIO_WAIT_WHILE macro, but if we are in the Main loop
4
easier to reason about than sector-based. Change the internal
4
do not release and then acquire ctx_ 's aiocontext.
5
loop iteration of streaming to track by bytes instead of sectors
6
(although we are still guaranteed that we iterate by steps that
7
are sector-aligned).
8
5
9
Signed-off-by: Eric Blake <eblake@redhat.com>
6
Once all Aiocontext locks go away, this macro will replace
10
Reviewed-by: John Snow <jsnow@redhat.com>
7
AIO_WAIT_WHILE.
11
Reviewed-by: Jeff Cody <jcody@redhat.com>
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Message-Id: <20220926093214.506243-5-eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
---
15
block/stream.c | 22 +++++++++-------------
16
include/block/aio-wait.h | 17 +++++++++++++----
16
1 file changed, 9 insertions(+), 13 deletions(-)
17
1 file changed, 13 insertions(+), 4 deletions(-)
17
18
18
diff --git a/block/stream.c b/block/stream.c
19
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/block/stream.c
21
--- a/include/block/aio-wait.h
21
+++ b/block/stream.c
22
+++ b/include/block/aio-wait.h
22
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
BlockBackend *blk = s->common.blk;
24
extern AioWait global_aio_wait;
24
BlockDriverState *bs = blk_bs(blk);
25
25
BlockDriverState *base = s->base;
26
/**
26
- int64_t sector_num = 0;
27
- * AIO_WAIT_WHILE:
27
- int64_t end = -1;
28
+ * AIO_WAIT_WHILE_INTERNAL:
28
+ int64_t offset = 0;
29
* @ctx: the aio context, or NULL if multiple aio contexts (for which the
29
uint64_t delay_ns = 0;
30
* caller does not hold a lock) are involved in the polling condition.
30
int error = 0;
31
* @cond: wait while this conditional expression is true
31
int ret = 0;
32
+ * @unlock: whether to unlock and then lock again @ctx. This apples
32
- int n = 0;
33
+ * only when waiting for another AioContext from the main loop.
33
+ int n = 0; /* sectors */
34
+ * Otherwise it's ignored.
34
void *buf;
35
*
35
36
* Wait while a condition is true. Use this to implement synchronous
36
if (!bs->backing) {
37
* operations that require event loop activity.
37
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
38
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
38
goto out;
39
* wait on conditions between two IOThreads since that could lead to deadlock,
39
}
40
* go via the main loop instead.
40
41
*/
41
- end = s->common.len >> BDRV_SECTOR_BITS;
42
-#define AIO_WAIT_WHILE(ctx, cond) ({ \
42
buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE);
43
+#define AIO_WAIT_WHILE_INTERNAL(ctx, cond, unlock) ({ \
43
44
bool waited_ = false; \
44
/* Turn on copy-on-read for the whole block device so that guest read
45
AioWait *wait_ = &global_aio_wait; \
45
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
46
AioContext *ctx_ = (ctx); \
46
bdrv_enable_copy_on_read(bs);
47
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
47
}
48
assert(qemu_get_current_aio_context() == \
48
49
qemu_get_aio_context()); \
49
- for (sector_num = 0; sector_num < end; sector_num += n) {
50
while ((cond)) { \
50
+ for ( ; offset < s->common.len; offset += n * BDRV_SECTOR_SIZE) {
51
- if (ctx_) { \
51
bool copy;
52
+ if (unlock && ctx_) { \
52
53
aio_context_release(ctx_); \
53
/* Note that even when no rate limit is applied we need to yield
54
} \
54
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
55
aio_poll(qemu_get_aio_context(), true); \
55
56
- if (ctx_) { \
56
copy = false;
57
+ if (unlock && ctx_) { \
57
58
aio_context_acquire(ctx_); \
58
- ret = bdrv_is_allocated(bs, sector_num,
59
} \
59
+ ret = bdrv_is_allocated(bs, offset / BDRV_SECTOR_SIZE,
60
waited_ = true; \
60
STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n);
61
@@ -XXX,XX +XXX,XX @@ extern AioWait global_aio_wait;
61
if (ret == 1) {
62
qatomic_dec(&wait_->num_waiters); \
62
/* Allocated in the top, no need to copy. */
63
waited_; })
63
} else if (ret >= 0) {
64
64
/* Copy if allocated in the intermediate images. Limit to the
65
+#define AIO_WAIT_WHILE(ctx, cond) \
65
- * known-unallocated area [sector_num, sector_num+n). */
66
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond, true)
66
+ * known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */
67
+
67
ret = bdrv_is_allocated_above(backing_bs(bs), base,
68
+#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \
68
- sector_num, n, &n);
69
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond, false)
69
+ offset / BDRV_SECTOR_SIZE, n, &n);
70
+
70
71
/**
71
/* Finish early if end of backing file has been reached */
72
* aio_wait_kick:
72
if (ret == 0 && n == 0) {
73
* Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During
73
- n = end - sector_num;
74
+ n = (s->common.len - offset) / BDRV_SECTOR_SIZE;
75
}
76
77
copy = (ret == 1);
78
}
79
- trace_stream_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
80
- n * BDRV_SECTOR_SIZE, ret);
81
+ trace_stream_one_iteration(s, offset, n * BDRV_SECTOR_SIZE, ret);
82
if (copy) {
83
- ret = stream_populate(blk, sector_num * BDRV_SECTOR_SIZE,
84
- n * BDRV_SECTOR_SIZE, buf);
85
+ ret = stream_populate(blk, offset, n * BDRV_SECTOR_SIZE, buf);
86
}
87
if (ret < 0) {
88
BlockErrorAction action =
89
--
74
--
90
1.8.3.1
75
2.37.3
91
92
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The user interface specifies job rate limits in bytes/second.
3
With "intact" we mean that all job.h functions implicitly
4
It's pointless to have our internal representation track things
4
take the lock. Therefore API callers are unmodified.
5
in sectors/second, particularly since we want to move away from
6
sector-based interfaces.
7
5
8
Fix up a doc typo found while verifying that the ratelimit
6
This means that:
9
code handles the scaling difference.
7
- many static functions that will be always called with job lock held
8
become _locked, and call _locked functions
9
- all public functions take the lock internally if needed, and call _locked
10
functions
11
- all public functions called internally by other functions in job.c will have a
12
_locked counterpart (sometimes public), to avoid deadlocks (job lock already taken).
13
These functions are not used for now.
14
- some public functions called only from exernal files (not job.c) do not
15
have _locked() counterpart and take the lock inside. Others won't need
16
the lock at all because use fields only set at initialization and
17
never modified.
10
18
11
Repetition of expressions like 'n * BDRV_SECTOR_SIZE' will be
19
job_{lock/unlock} is independent from real_job_{lock/unlock}.
12
cleaned up later when functions are converted to iterate over
13
images by bytes rather than by sectors.
14
20
15
Signed-off-by: Eric Blake <eblake@redhat.com>
21
Note: at this stage, job_{lock/unlock} and job lock guard macros
16
Reviewed-by: John Snow <jsnow@redhat.com>
22
are *nop*
17
Reviewed-by: Jeff Cody <jcody@redhat.com>
23
24
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
26
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
28
Message-Id: <20220926093214.506243-6-eesposit@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
30
---
21
block/backup.c | 5 +++--
31
include/qemu/job.h | 138 +++++++++-
22
block/commit.c | 5 +++--
32
job.c | 610 ++++++++++++++++++++++++++++++++-------------
23
block/mirror.c | 13 +++++++------
33
2 files changed, 561 insertions(+), 187 deletions(-)
24
block/stream.c | 5 +++--
25
include/qemu/ratelimit.h | 3 ++-
26
5 files changed, 18 insertions(+), 13 deletions(-)
27
34
28
diff --git a/block/backup.c b/block/backup.c
35
diff --git a/include/qemu/job.h b/include/qemu/job.h
29
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
30
--- a/block/backup.c
37
--- a/include/qemu/job.h
31
+++ b/block/backup.c
38
+++ b/include/qemu/job.h
32
@@ -XXX,XX +XXX,XX @@ static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp)
39
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
33
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
40
*/
41
void job_txn_unref(JobTxn *txn);
42
43
+/*
44
+ * Same as job_txn_unref(), but called with job lock held.
45
+ * Might release the lock temporarily.
46
+ */
47
+void job_txn_unref_locked(JobTxn *txn);
48
+
49
/**
50
* Create a new long-running job and return it.
51
+ * Called with job_mutex *not* held.
52
*
53
* @job_id: The id of the newly-created job, or %NULL for internal jobs
54
* @driver: The class object for the newly-created job.
55
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
56
*/
57
void job_ref(Job *job);
58
59
+/* Same as job_ref(), but called with job lock held. */
60
+void job_ref_locked(Job *job);
61
+
62
/**
63
* Release a reference that was previously acquired with job_ref() or
64
* job_create(). If it's the last reference to the object, it will be freed.
65
*/
66
void job_unref(Job *job);
67
68
+/* Same as job_unref(), but called with job lock held. */
69
+void job_unref_locked(Job *job);
70
+
71
/**
72
* @job: The job that has made progress
73
* @done: How much progress the job made since the last call
74
*
75
* Updates the progress counter of the job.
76
+ *
77
+ * May be called with mutex held or not held.
78
*/
79
void job_progress_update(Job *job, uint64_t done);
80
81
@@ -XXX,XX +XXX,XX @@ void job_progress_update(Job *job, uint64_t done);
82
*
83
* Sets the expected end value of the progress counter of a job so that a
84
* completion percentage can be calculated when the progress is updated.
85
+ *
86
+ * May be called with mutex held or not held.
87
*/
88
void job_progress_set_remaining(Job *job, uint64_t remaining);
89
90
@@ -XXX,XX +XXX,XX @@ void job_progress_set_remaining(Job *job, uint64_t remaining);
91
* length before, and job_progress_update() afterwards.
92
* (So the operation acts as a parenthesis in regards to the main job
93
* operation running in background.)
94
+ *
95
+ * May be called with mutex held or not held.
96
*/
97
void job_progress_increase_remaining(Job *job, uint64_t delta);
98
99
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta);
100
*/
101
void job_enter_cond(Job *job, bool(*fn)(Job *job));
102
103
+/*
104
+ * Same as job_enter_cond(), but called with job lock held.
105
+ * Might release the lock temporarily.
106
+ */
107
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
108
+
109
/**
110
* @job: A job that has not yet been started.
111
*
112
* Begins execution of a job.
113
* Takes ownership of one reference to the job object.
114
+ *
115
+ * Called with job_mutex *not* held.
116
*/
117
void job_start(Job *job);
118
119
@@ -XXX,XX +XXX,XX @@ void job_start(Job *job);
120
* @job: The job to enter.
121
*
122
* Continue the specified job by entering the coroutine.
123
+ * Called with job_mutex *not* held.
124
*/
125
void job_enter(Job *job);
126
127
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job);
128
*
129
* Pause now if job_pause() has been called. Jobs that perform lots of I/O
130
* must call this between requests so that the job can be paused.
131
+ *
132
+ * Called with job_mutex *not* held.
133
*/
134
void coroutine_fn job_pause_point(Job *job);
135
136
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job);
137
* @job: The job that calls the function.
138
*
139
* Yield the job coroutine.
140
+ * Called with job_mutex *not* held.
141
*/
142
void coroutine_fn job_yield(Job *job);
143
144
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_yield(Job *job);
145
* Put the job to sleep (assuming that it wasn't canceled) for @ns
146
* %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately
147
* interrupt the wait.
148
+ *
149
+ * Called with job_mutex *not* held.
150
*/
151
void coroutine_fn job_sleep_ns(Job *job, int64_t ns);
152
153
@@ -XXX,XX +XXX,XX @@ const char *job_type_str(const Job *job);
154
/** Returns true if the job should not be visible to the management layer. */
155
bool job_is_internal(Job *job);
156
157
-/** Returns whether the job is being cancelled. */
158
+/**
159
+ * Returns whether the job is being cancelled.
160
+ * Called with job_mutex *not* held.
161
+ */
162
bool job_is_cancelled(Job *job);
163
164
+/* Same as job_is_cancelled(), but called with job lock held. */
165
+bool job_is_cancelled_locked(Job *job);
166
+
167
/**
168
* Returns whether the job is scheduled for cancellation (at an
169
* indefinite point).
170
+ * Called with job_mutex *not* held.
171
*/
172
bool job_cancel_requested(Job *job);
173
174
-/** Returns whether the job is in a completed state. */
175
+/**
176
+ * Returns whether the job is in a completed state.
177
+ * Called with job_mutex *not* held.
178
+ */
179
bool job_is_completed(Job *job);
180
181
-/** Returns whether the job is ready to be completed. */
182
+/* Same as job_is_completed(), but called with job lock held. */
183
+bool job_is_completed_locked(Job *job);
184
+
185
+/**
186
+ * Returns whether the job is ready to be completed.
187
+ * Called with job_mutex *not* held.
188
+ */
189
bool job_is_ready(Job *job);
190
191
+/* Same as job_is_ready(), but called with job lock held. */
192
+bool job_is_ready_locked(Job *job);
193
+
194
/**
195
* Request @job to pause at the next pause point. Must be paired with
196
* job_resume(). If the job is supposed to be resumed by user action, call
197
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job);
198
*/
199
void job_pause(Job *job);
200
201
+/* Same as job_pause(), but called with job lock held. */
202
+void job_pause_locked(Job *job);
203
+
204
/** Resumes a @job paused with job_pause. */
205
void job_resume(Job *job);
206
207
+/*
208
+ * Same as job_resume(), but called with job lock held.
209
+ * Might release the lock temporarily.
210
+ */
211
+void job_resume_locked(Job *job);
212
+
213
/**
214
* Asynchronously pause the specified @job.
215
* Do not allow a resume until a matching call to job_user_resume.
216
*/
217
void job_user_pause(Job *job, Error **errp);
218
219
+/* Same as job_user_pause(), but called with job lock held. */
220
+void job_user_pause_locked(Job *job, Error **errp);
221
+
222
/** Returns true if the job is user-paused. */
223
bool job_user_paused(Job *job);
224
225
+/* Same as job_user_paused(), but called with job lock held. */
226
+bool job_user_paused_locked(Job *job);
227
+
228
/**
229
* Resume the specified @job.
230
* Must be paired with a preceding job_user_pause.
231
*/
232
void job_user_resume(Job *job, Error **errp);
233
234
+/*
235
+ * Same as job_user_resume(), but called with job lock held.
236
+ * Might release the lock temporarily.
237
+ */
238
+void job_user_resume_locked(Job *job, Error **errp);
239
+
240
/**
241
* Get the next element from the list of block jobs after @job, or the
242
* first one if @job is %NULL.
243
@@ -XXX,XX +XXX,XX @@ void job_user_resume(Job *job, Error **errp);
244
*/
245
Job *job_next(Job *job);
246
247
+/* Same as job_next(), but called with job lock held. */
248
+Job *job_next_locked(Job *job);
249
+
250
/**
251
* Get the job identified by @id (which must not be %NULL).
252
*
253
@@ -XXX,XX +XXX,XX @@ Job *job_next(Job *job);
254
*/
255
Job *job_get(const char *id);
256
257
+/* Same as job_get(), but called with job lock held. */
258
+Job *job_get_locked(const char *id);
259
+
260
/**
261
* Check whether the verb @verb can be applied to @job in its current state.
262
* Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
263
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id);
264
*/
265
int job_apply_verb(Job *job, JobVerb verb, Error **errp);
266
267
-/** The @job could not be started, free it. */
268
+/* Same as job_apply_verb, but called with job lock held. */
269
+int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
270
+
271
+/**
272
+ * The @job could not be started, free it.
273
+ * Called with job_mutex *not* held.
274
+ */
275
void job_early_fail(Job *job);
276
277
-/** Moves the @job from RUNNING to READY */
278
+/**
279
+ * Moves the @job from RUNNING to READY.
280
+ * Called with job_mutex *not* held.
281
+ */
282
void job_transition_to_ready(Job *job);
283
284
/** Asynchronously complete the specified @job. */
285
void job_complete(Job *job, Error **errp);
286
287
+/*
288
+ * Same as job_complete(), but called with job lock held.
289
+ * Might release the lock temporarily.
290
+ */
291
+void job_complete_locked(Job *job, Error **errp);
292
+
293
/**
294
* Asynchronously cancel the specified @job. If @force is true, the job should
295
* be cancelled immediately without waiting for a consistent state.
296
*/
297
void job_cancel(Job *job, bool force);
298
299
+/* Same as job_cancel(), but called with job lock held. */
300
+void job_cancel_locked(Job *job, bool force);
301
+
302
/**
303
* Cancels the specified job like job_cancel(), but may refuse to do so if the
304
* operation isn't meaningful in the current state of the job.
305
*/
306
void job_user_cancel(Job *job, bool force, Error **errp);
307
308
+/* Same as job_user_cancel(), but called with job lock held. */
309
+void job_user_cancel_locked(Job *job, bool force, Error **errp);
310
+
311
/**
312
* Synchronously cancel the @job. The completion callback is called
313
* before the function returns. If @force is false, the job may
314
@@ -XXX,XX +XXX,XX @@ void job_user_cancel(Job *job, bool force, Error **errp);
315
*/
316
int job_cancel_sync(Job *job, bool force);
317
318
-/** Synchronously force-cancels all jobs using job_cancel_sync(). */
319
+/* Same as job_cancel_sync, but called with job lock held. */
320
+int job_cancel_sync_locked(Job *job, bool force);
321
+
322
+/**
323
+ * Synchronously force-cancels all jobs using job_cancel_sync_locked().
324
+ *
325
+ * Called with job_lock *not* held.
326
+ */
327
void job_cancel_sync_all(void);
328
329
/**
330
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
331
*/
332
int job_complete_sync(Job *job, Error **errp);
333
334
+/* Same as job_complete_sync, but called with job lock held. */
335
+int job_complete_sync_locked(Job *job, Error **errp);
336
+
337
/**
338
* For a @job that has finished its work and is pending awaiting explicit
339
* acknowledgement to commit its work, this will commit that work.
340
@@ -XXX,XX +XXX,XX @@ int job_complete_sync(Job *job, Error **errp);
341
*/
342
void job_finalize(Job *job, Error **errp);
343
344
+/* Same as job_finalize(), but called with job lock held. */
345
+void job_finalize_locked(Job *job, Error **errp);
346
+
347
/**
348
* Remove the concluded @job from the query list and resets the passed pointer
349
* to %NULL. Returns an error if the job is not actually concluded.
350
*/
351
void job_dismiss(Job **job, Error **errp);
352
353
+/* Same as job_dismiss(), but called with job lock held. */
354
+void job_dismiss_locked(Job **job, Error **errp);
355
+
356
/**
357
* Synchronously finishes the given @job. If @finish is given, it is called to
358
* trigger completion or cancellation of the job.
359
@@ -XXX,XX +XXX,XX @@ void job_dismiss(Job **job, Error **errp);
360
*
361
* Callers must hold the AioContext lock of job->aio_context.
362
*/
363
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp);
364
+int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
365
+ Error **errp);
366
+
367
+/*
368
+ * Same as job_finish_sync(), but called with job lock held.
369
+ * Might release the lock temporarily.
370
+ */
371
+int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
372
+ Error **errp);
373
374
#endif
375
diff --git a/job.c b/job.c
376
index XXXXXXX..XXXXXXX 100644
377
--- a/job.c
378
+++ b/job.c
379
@@ -XXX,XX +XXX,XX @@
380
*/
381
QemuMutex job_mutex;
382
383
+/* Protected by job_mutex */
384
static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs);
385
386
/* Job State Transition Table */
387
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void)
388
return txn;
389
}
390
391
-static void job_txn_ref(JobTxn *txn)
392
+/* Called with job_mutex held. */
393
+static void job_txn_ref_locked(JobTxn *txn)
394
{
395
txn->refcnt++;
396
}
397
398
-void job_txn_unref(JobTxn *txn)
399
+void job_txn_unref_locked(JobTxn *txn)
400
{
401
if (txn && --txn->refcnt == 0) {
402
g_free(txn);
403
}
404
}
405
406
+void job_txn_unref(JobTxn *txn)
407
+{
408
+ JOB_LOCK_GUARD();
409
+ job_txn_unref_locked(txn);
410
+}
411
+
412
/**
413
* @txn: The transaction (may be NULL)
414
* @job: Job to add to the transaction
415
@@ -XXX,XX +XXX,XX @@ void job_txn_unref(JobTxn *txn)
416
* the reference that is automatically grabbed here.
417
*
418
* If @txn is NULL, the function does nothing.
419
+ *
420
+ * Called with job_mutex held.
421
*/
422
-static void job_txn_add_job(JobTxn *txn, Job *job)
423
+static void job_txn_add_job_locked(JobTxn *txn, Job *job)
424
{
425
if (!txn) {
34
return;
426
return;
35
}
427
@@ -XXX,XX +XXX,XX @@ static void job_txn_add_job(JobTxn *txn, Job *job)
36
- ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
428
job->txn = txn;
37
+ ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
429
38
}
430
QLIST_INSERT_HEAD(&txn->jobs, job, txn_list);
39
431
- job_txn_ref(txn);
40
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
432
+ job_txn_ref_locked(txn);
41
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job)
433
}
434
435
-static void job_txn_del_job(Job *job)
436
+/* Called with job_mutex held. */
437
+static void job_txn_del_job_locked(Job *job)
438
{
439
if (job->txn) {
440
QLIST_REMOVE(job, txn_list);
441
- job_txn_unref(job->txn);
442
+ job_txn_unref_locked(job->txn);
443
job->txn = NULL;
444
}
445
}
446
447
-static int job_txn_apply(Job *job, int fn(Job *))
448
+/* Called with job_mutex held, but releases it temporarily. */
449
+static int job_txn_apply_locked(Job *job, int fn(Job *))
450
{
451
AioContext *inner_ctx;
452
Job *other_job, *next;
453
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply(Job *job, int fn(Job *))
454
* we need to release it here to avoid holding the lock twice - which would
455
* break AIO_WAIT_WHILE from within fn.
42
*/
456
*/
43
if (job->common.speed) {
457
- job_ref(job);
44
uint64_t delay_ns = ratelimit_calculate_delay(&job->limit,
458
+ job_ref_locked(job);
45
- job->sectors_read);
459
aio_context_release(job->aio_context);
46
+ job->sectors_read *
460
47
+ BDRV_SECTOR_SIZE);
461
QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) {
48
job->sectors_read = 0;
462
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply(Job *job, int fn(Job *))
49
block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns);
463
* can't use a local variable to cache it.
464
*/
465
aio_context_acquire(job->aio_context);
466
- job_unref(job);
467
+ job_unref_locked(job);
468
return rc;
469
}
470
471
@@ -XXX,XX +XXX,XX @@ bool job_is_internal(Job *job)
472
return (job->id == NULL);
473
}
474
475
-static void job_state_transition(Job *job, JobStatus s1)
476
+/* Called with job_mutex held. */
477
+static void job_state_transition_locked(Job *job, JobStatus s1)
478
{
479
JobStatus s0 = job->status;
480
assert(s1 >= 0 && s1 < JOB_STATUS__MAX);
481
@@ -XXX,XX +XXX,XX @@ static void job_state_transition(Job *job, JobStatus s1)
482
}
483
}
484
485
-int job_apply_verb(Job *job, JobVerb verb, Error **errp)
486
+int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp)
487
{
488
JobStatus s0 = job->status;
489
assert(verb >= 0 && verb < JOB_VERB__MAX);
490
@@ -XXX,XX +XXX,XX @@ int job_apply_verb(Job *job, JobVerb verb, Error **errp)
491
return -EPERM;
492
}
493
494
+int job_apply_verb(Job *job, JobVerb verb, Error **errp)
495
+{
496
+ JOB_LOCK_GUARD();
497
+ return job_apply_verb_locked(job, verb, errp);
498
+}
499
+
500
JobType job_type(const Job *job)
501
{
502
return job->driver->job_type;
503
@@ -XXX,XX +XXX,XX @@ const char *job_type_str(const Job *job)
504
return JobType_str(job_type(job));
505
}
506
507
-bool job_is_cancelled(Job *job)
508
+bool job_is_cancelled_locked(Job *job)
509
{
510
/* force_cancel may be true only if cancelled is true, too */
511
assert(job->cancelled || !job->force_cancel);
512
return job->force_cancel;
513
}
514
515
-bool job_cancel_requested(Job *job)
516
+bool job_is_cancelled(Job *job)
517
+{
518
+ JOB_LOCK_GUARD();
519
+ return job_is_cancelled_locked(job);
520
+}
521
+
522
+/* Called with job_mutex held. */
523
+static bool job_cancel_requested_locked(Job *job)
524
{
525
return job->cancelled;
526
}
527
528
-bool job_is_ready(Job *job)
529
+bool job_cancel_requested(Job *job)
530
+{
531
+ JOB_LOCK_GUARD();
532
+ return job_cancel_requested_locked(job);
533
+}
534
+
535
+bool job_is_ready_locked(Job *job)
536
{
537
switch (job->status) {
538
case JOB_STATUS_UNDEFINED:
539
@@ -XXX,XX +XXX,XX @@ bool job_is_ready(Job *job)
540
return false;
541
}
542
543
-bool job_is_completed(Job *job)
544
+bool job_is_ready(Job *job)
545
+{
546
+ JOB_LOCK_GUARD();
547
+ return job_is_ready_locked(job);
548
+}
549
+
550
+bool job_is_completed_locked(Job *job)
551
{
552
switch (job->status) {
553
case JOB_STATUS_UNDEFINED:
554
@@ -XXX,XX +XXX,XX @@ bool job_is_completed(Job *job)
555
return false;
556
}
557
558
-static bool job_started(Job *job)
559
+bool job_is_completed(Job *job)
560
+{
561
+ JOB_LOCK_GUARD();
562
+ return job_is_completed_locked(job);
563
+}
564
+
565
+static bool job_started_locked(Job *job)
566
{
567
return job->co;
568
}
569
570
-static bool job_should_pause(Job *job)
571
+/* Called with job_mutex held. */
572
+static bool job_should_pause_locked(Job *job)
573
{
574
return job->pause_count > 0;
575
}
576
577
-Job *job_next(Job *job)
578
+Job *job_next_locked(Job *job)
579
{
580
if (!job) {
581
return QLIST_FIRST(&jobs);
582
@@ -XXX,XX +XXX,XX @@ Job *job_next(Job *job)
583
return QLIST_NEXT(job, job_list);
584
}
585
586
-Job *job_get(const char *id)
587
+Job *job_next(Job *job)
588
+{
589
+ JOB_LOCK_GUARD();
590
+ return job_next_locked(job);
591
+}
592
+
593
+Job *job_get_locked(const char *id)
594
{
595
Job *job;
596
597
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id)
598
return NULL;
599
}
600
601
+Job *job_get(const char *id)
602
+{
603
+ JOB_LOCK_GUARD();
604
+ return job_get_locked(id);
605
+}
606
+
607
+/* Called with job_mutex *not* held. */
608
static void job_sleep_timer_cb(void *opaque)
609
{
610
Job *job = opaque;
611
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
612
{
613
Job *job;
614
615
+ JOB_LOCK_GUARD();
616
+
617
if (job_id) {
618
if (flags & JOB_INTERNAL) {
619
error_setg(errp, "Cannot specify job ID for internal job");
620
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
621
error_setg(errp, "Invalid job ID '%s'", job_id);
622
return NULL;
623
}
624
- if (job_get(job_id)) {
625
+ if (job_get_locked(job_id)) {
626
error_setg(errp, "Job ID '%s' already in use", job_id);
627
return NULL;
628
}
629
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
630
notifier_list_init(&job->on_ready);
631
notifier_list_init(&job->on_idle);
632
633
- job_state_transition(job, JOB_STATUS_CREATED);
634
+ job_state_transition_locked(job, JOB_STATUS_CREATED);
635
aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
636
QEMU_CLOCK_REALTIME, SCALE_NS,
637
job_sleep_timer_cb, job);
638
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
639
* consolidating the job management logic */
640
if (!txn) {
641
txn = job_txn_new();
642
- job_txn_add_job(txn, job);
643
- job_txn_unref(txn);
644
+ job_txn_add_job_locked(txn, job);
645
+ job_txn_unref_locked(txn);
50
} else {
646
} else {
51
diff --git a/block/commit.c b/block/commit.c
647
- job_txn_add_job(txn, job);
52
index XXXXXXX..XXXXXXX 100644
648
+ job_txn_add_job_locked(txn, job);
53
--- a/block/commit.c
649
}
54
+++ b/block/commit.c
650
55
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
651
return job;
56
s->common.offset += n * BDRV_SECTOR_SIZE;
652
}
57
653
58
if (copy && s->common.speed) {
654
-void job_ref(Job *job)
59
- delay_ns = ratelimit_calculate_delay(&s->limit, n);
655
+void job_ref_locked(Job *job)
60
+ delay_ns = ratelimit_calculate_delay(&s->limit,
656
{
61
+ n * BDRV_SECTOR_SIZE);
657
++job->refcnt;
658
}
659
660
-void job_unref(Job *job)
661
+void job_ref(Job *job)
662
+{
663
+ JOB_LOCK_GUARD();
664
+ job_ref_locked(job);
665
+}
666
+
667
+void job_unref_locked(Job *job)
668
{
669
GLOBAL_STATE_CODE();
670
671
@@ -XXX,XX +XXX,XX @@ void job_unref(Job *job)
672
assert(!job->txn);
673
674
if (job->driver->free) {
675
+ job_unlock();
676
job->driver->free(job);
677
+ job_lock();
62
}
678
}
63
}
679
64
680
QLIST_REMOVE(job, job_list);
65
@@ -XXX,XX +XXX,XX @@ static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
681
@@ -XXX,XX +XXX,XX @@ void job_unref(Job *job)
66
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
682
}
683
}
684
685
+void job_unref(Job *job)
686
+{
687
+ JOB_LOCK_GUARD();
688
+ job_unref_locked(job);
689
+}
690
+
691
void job_progress_update(Job *job, uint64_t done)
692
{
693
progress_work_done(&job->progress, done);
694
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta)
695
696
/**
697
* To be called when a cancelled job is finalised.
698
+ * Called with job_mutex held.
699
*/
700
-static void job_event_cancelled(Job *job)
701
+static void job_event_cancelled_locked(Job *job)
702
{
703
notifier_list_notify(&job->on_finalize_cancelled, job);
704
}
705
706
/**
707
* To be called when a successfully completed job is finalised.
708
+ * Called with job_mutex held.
709
*/
710
-static void job_event_completed(Job *job)
711
+static void job_event_completed_locked(Job *job)
712
{
713
notifier_list_notify(&job->on_finalize_completed, job);
714
}
715
716
-static void job_event_pending(Job *job)
717
+/* Called with job_mutex held. */
718
+static void job_event_pending_locked(Job *job)
719
{
720
notifier_list_notify(&job->on_pending, job);
721
}
722
723
-static void job_event_ready(Job *job)
724
+/* Called with job_mutex held. */
725
+static void job_event_ready_locked(Job *job)
726
{
727
notifier_list_notify(&job->on_ready, job);
728
}
729
730
-static void job_event_idle(Job *job)
731
+/* Called with job_mutex held. */
732
+static void job_event_idle_locked(Job *job)
733
{
734
notifier_list_notify(&job->on_idle, job);
735
}
736
737
-void job_enter_cond(Job *job, bool(*fn)(Job *job))
738
+void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
739
{
740
- if (!job_started(job)) {
741
+ if (!job_started_locked(job)) {
67
return;
742
return;
68
}
743
}
69
- ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
744
if (job->deferred_to_main_loop) {
70
+ ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
745
@@ -XXX,XX +XXX,XX @@ void job_enter_cond(Job *job, bool(*fn)(Job *job))
71
}
746
timer_del(&job->sleep_timer);
72
747
job->busy = true;
73
static const BlockJobDriver commit_job_driver = {
748
real_job_unlock();
74
diff --git a/block/mirror.c b/block/mirror.c
749
+ job_unlock();
75
index XXXXXXX..XXXXXXX 100644
750
aio_co_enter(job->aio_context, job->co);
76
--- a/block/mirror.c
751
+ job_lock();
77
+++ b/block/mirror.c
752
+}
78
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
753
+
79
bitmap_set(s->in_flight_bitmap, sector_num / sectors_per_chunk, nb_chunks);
754
+void job_enter_cond(Job *job, bool(*fn)(Job *job))
80
while (nb_chunks > 0 && sector_num < end) {
755
+{
81
int64_t ret;
756
+ JOB_LOCK_GUARD();
82
- int io_sectors, io_sectors_acct;
757
+ job_enter_cond_locked(job, fn);
83
+ int io_sectors;
758
}
84
+ int64_t io_bytes_acct;
759
85
BlockDriverState *file;
760
void job_enter(Job *job)
86
enum MirrorMethod {
761
{
87
MIRROR_METHOD_COPY,
762
- job_enter_cond(job, NULL);
88
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
763
+ JOB_LOCK_GUARD();
89
switch (mirror_method) {
764
+ job_enter_cond_locked(job, NULL);
90
case MIRROR_METHOD_COPY:
765
}
91
io_sectors = mirror_do_read(s, sector_num, io_sectors);
766
92
- io_sectors_acct = io_sectors;
767
/* Yield, and schedule a timer to reenter the coroutine after @ns nanoseconds.
93
+ io_bytes_acct = io_sectors * BDRV_SECTOR_SIZE;
768
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
94
break;
769
* is allowed and cancels the timer.
95
case MIRROR_METHOD_ZERO:
770
*
96
case MIRROR_METHOD_DISCARD:
771
* If @ns is (uint64_t) -1, no timer is scheduled and job_enter() must be
97
mirror_do_zero_or_discard(s, sector_num, io_sectors,
772
- * called explicitly. */
98
mirror_method == MIRROR_METHOD_DISCARD);
773
-static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
99
if (write_zeroes_ok) {
774
+ * called explicitly.
100
- io_sectors_acct = 0;
775
+ *
101
+ io_bytes_acct = 0;
776
+ * Called with job_mutex held, but releases it temporarily.
102
} else {
777
+ */
103
- io_sectors_acct = io_sectors;
778
+static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
104
+ io_bytes_acct = io_sectors * BDRV_SECTOR_SIZE;
779
{
105
}
780
real_job_lock();
106
break;
781
if (ns != -1) {
107
default:
782
timer_mod(&job->sleep_timer, ns);
108
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
783
}
109
sector_num += io_sectors;
784
job->busy = false;
110
nb_chunks -= DIV_ROUND_UP(io_sectors, sectors_per_chunk);
785
- job_event_idle(job);
111
if (s->common.speed) {
786
+ job_event_idle_locked(job);
112
- delay_ns = ratelimit_calculate_delay(&s->limit, io_sectors_acct);
787
real_job_unlock();
113
+ delay_ns = ratelimit_calculate_delay(&s->limit, io_bytes_acct);
788
+ job_unlock();
789
qemu_coroutine_yield();
790
+ job_lock();
791
792
/* Set by job_enter_cond() before re-entering the coroutine. */
793
assert(job->busy);
794
}
795
796
-void coroutine_fn job_pause_point(Job *job)
797
+/* Called with job_mutex held, but releases it temporarily. */
798
+static void coroutine_fn job_pause_point_locked(Job *job)
799
{
800
- assert(job && job_started(job));
801
+ assert(job && job_started_locked(job));
802
803
- if (!job_should_pause(job)) {
804
+ if (!job_should_pause_locked(job)) {
805
return;
806
}
807
- if (job_is_cancelled(job)) {
808
+ if (job_is_cancelled_locked(job)) {
809
return;
810
}
811
812
if (job->driver->pause) {
813
+ job_unlock();
814
job->driver->pause(job);
815
+ job_lock();
816
}
817
818
- if (job_should_pause(job) && !job_is_cancelled(job)) {
819
+ if (job_should_pause_locked(job) && !job_is_cancelled_locked(job)) {
820
JobStatus status = job->status;
821
- job_state_transition(job, status == JOB_STATUS_READY
822
- ? JOB_STATUS_STANDBY
823
- : JOB_STATUS_PAUSED);
824
+ job_state_transition_locked(job, status == JOB_STATUS_READY
825
+ ? JOB_STATUS_STANDBY
826
+ : JOB_STATUS_PAUSED);
827
job->paused = true;
828
- job_do_yield(job, -1);
829
+ job_do_yield_locked(job, -1);
830
job->paused = false;
831
- job_state_transition(job, status);
832
+ job_state_transition_locked(job, status);
833
}
834
835
if (job->driver->resume) {
836
+ job_unlock();
837
job->driver->resume(job);
838
+ job_lock();
839
}
840
}
841
842
-void coroutine_fn job_yield(Job *job)
843
+void coroutine_fn job_pause_point(Job *job)
844
+{
845
+ JOB_LOCK_GUARD();
846
+ job_pause_point_locked(job);
847
+}
848
+
849
+static void coroutine_fn job_yield_locked(Job *job)
850
{
851
assert(job->busy);
852
853
/* Check cancellation *before* setting busy = false, too! */
854
- if (job_is_cancelled(job)) {
855
+ if (job_is_cancelled_locked(job)) {
856
return;
857
}
858
859
- if (!job_should_pause(job)) {
860
- job_do_yield(job, -1);
861
+ if (!job_should_pause_locked(job)) {
862
+ job_do_yield_locked(job, -1);
863
}
864
865
- job_pause_point(job);
866
+ job_pause_point_locked(job);
867
+}
868
+
869
+void coroutine_fn job_yield(Job *job)
870
+{
871
+ JOB_LOCK_GUARD();
872
+ job_yield_locked(job);
873
}
874
875
void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
876
{
877
+ JOB_LOCK_GUARD();
878
assert(job->busy);
879
880
/* Check cancellation *before* setting busy = false, too! */
881
- if (job_is_cancelled(job)) {
882
+ if (job_is_cancelled_locked(job)) {
883
return;
884
}
885
886
- if (!job_should_pause(job)) {
887
- job_do_yield(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
888
+ if (!job_should_pause_locked(job)) {
889
+ job_do_yield_locked(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns);
890
}
891
892
- job_pause_point(job);
893
+ job_pause_point_locked(job);
894
}
895
896
-/* Assumes the block_job_mutex is held */
897
-static bool job_timer_not_pending(Job *job)
898
+/* Assumes the job_mutex is held */
899
+static bool job_timer_not_pending_locked(Job *job)
900
{
901
return !timer_pending(&job->sleep_timer);
902
}
903
904
-void job_pause(Job *job)
905
+void job_pause_locked(Job *job)
906
{
907
job->pause_count++;
908
if (!job->paused) {
909
- job_enter(job);
910
+ job_enter_cond_locked(job, NULL);
911
}
912
}
913
914
-void job_resume(Job *job)
915
+void job_pause(Job *job)
916
+{
917
+ JOB_LOCK_GUARD();
918
+ job_pause_locked(job);
919
+}
920
+
921
+void job_resume_locked(Job *job)
922
{
923
assert(job->pause_count > 0);
924
job->pause_count--;
925
@@ -XXX,XX +XXX,XX @@ void job_resume(Job *job)
926
}
927
928
/* kick only if no timer is pending */
929
- job_enter_cond(job, job_timer_not_pending);
930
+ job_enter_cond_locked(job, job_timer_not_pending_locked);
931
}
932
933
-void job_user_pause(Job *job, Error **errp)
934
+void job_resume(Job *job)
935
{
936
- if (job_apply_verb(job, JOB_VERB_PAUSE, errp)) {
937
+ JOB_LOCK_GUARD();
938
+ job_resume_locked(job);
939
+}
940
+
941
+void job_user_pause_locked(Job *job, Error **errp)
942
+{
943
+ if (job_apply_verb_locked(job, JOB_VERB_PAUSE, errp)) {
944
return;
945
}
946
if (job->user_paused) {
947
@@ -XXX,XX +XXX,XX @@ void job_user_pause(Job *job, Error **errp)
948
return;
949
}
950
job->user_paused = true;
951
- job_pause(job);
952
+ job_pause_locked(job);
953
}
954
955
-bool job_user_paused(Job *job)
956
+void job_user_pause(Job *job, Error **errp)
957
+{
958
+ JOB_LOCK_GUARD();
959
+ job_user_pause_locked(job, errp);
960
+}
961
+
962
+bool job_user_paused_locked(Job *job)
963
{
964
return job->user_paused;
965
}
966
967
-void job_user_resume(Job *job, Error **errp)
968
+bool job_user_paused(Job *job)
969
+{
970
+ JOB_LOCK_GUARD();
971
+ return job_user_paused_locked(job);
972
+}
973
+
974
+void job_user_resume_locked(Job *job, Error **errp)
975
{
976
assert(job);
977
GLOBAL_STATE_CODE();
978
@@ -XXX,XX +XXX,XX @@ void job_user_resume(Job *job, Error **errp)
979
error_setg(errp, "Can't resume a job that was not paused");
980
return;
981
}
982
- if (job_apply_verb(job, JOB_VERB_RESUME, errp)) {
983
+ if (job_apply_verb_locked(job, JOB_VERB_RESUME, errp)) {
984
return;
985
}
986
if (job->driver->user_resume) {
987
+ job_unlock();
988
job->driver->user_resume(job);
989
+ job_lock();
990
}
991
job->user_paused = false;
992
- job_resume(job);
993
+ job_resume_locked(job);
994
}
995
996
-static void job_do_dismiss(Job *job)
997
+void job_user_resume(Job *job, Error **errp)
998
+{
999
+ JOB_LOCK_GUARD();
1000
+ job_user_resume_locked(job, errp);
1001
+}
1002
+
1003
+/* Called with job_mutex held, but releases it temporarily. */
1004
+static void job_do_dismiss_locked(Job *job)
1005
{
1006
assert(job);
1007
job->busy = false;
1008
job->paused = false;
1009
job->deferred_to_main_loop = true;
1010
1011
- job_txn_del_job(job);
1012
+ job_txn_del_job_locked(job);
1013
1014
- job_state_transition(job, JOB_STATUS_NULL);
1015
- job_unref(job);
1016
+ job_state_transition_locked(job, JOB_STATUS_NULL);
1017
+ job_unref_locked(job);
1018
}
1019
1020
-void job_dismiss(Job **jobptr, Error **errp)
1021
+void job_dismiss_locked(Job **jobptr, Error **errp)
1022
{
1023
Job *job = *jobptr;
1024
/* similarly to _complete, this is QMP-interface only. */
1025
assert(job->id);
1026
- if (job_apply_verb(job, JOB_VERB_DISMISS, errp)) {
1027
+ if (job_apply_verb_locked(job, JOB_VERB_DISMISS, errp)) {
1028
return;
1029
}
1030
1031
- job_do_dismiss(job);
1032
+ job_do_dismiss_locked(job);
1033
*jobptr = NULL;
1034
}
1035
1036
+void job_dismiss(Job **jobptr, Error **errp)
1037
+{
1038
+ JOB_LOCK_GUARD();
1039
+ job_dismiss_locked(jobptr, errp);
1040
+}
1041
+
1042
void job_early_fail(Job *job)
1043
{
1044
+ JOB_LOCK_GUARD();
1045
assert(job->status == JOB_STATUS_CREATED);
1046
- job_do_dismiss(job);
1047
+ job_do_dismiss_locked(job);
1048
}
1049
1050
-static void job_conclude(Job *job)
1051
+/* Called with job_mutex held. */
1052
+static void job_conclude_locked(Job *job)
1053
{
1054
- job_state_transition(job, JOB_STATUS_CONCLUDED);
1055
- if (job->auto_dismiss || !job_started(job)) {
1056
- job_do_dismiss(job);
1057
+ job_state_transition_locked(job, JOB_STATUS_CONCLUDED);
1058
+ if (job->auto_dismiss || !job_started_locked(job)) {
1059
+ job_do_dismiss_locked(job);
1060
}
1061
}
1062
1063
-static void job_update_rc(Job *job)
1064
+/* Called with job_mutex held. */
1065
+static void job_update_rc_locked(Job *job)
1066
{
1067
- if (!job->ret && job_is_cancelled(job)) {
1068
+ if (!job->ret && job_is_cancelled_locked(job)) {
1069
job->ret = -ECANCELED;
1070
}
1071
if (job->ret) {
1072
if (!job->err) {
1073
error_setg(&job->err, "%s", strerror(-job->ret));
114
}
1074
}
115
}
1075
- job_state_transition(job, JOB_STATUS_ABORTING);
116
return delay_ns;
1076
+ job_state_transition_locked(job, JOB_STATUS_ABORTING);
117
@@ -XXX,XX +XXX,XX @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
1077
}
118
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
1078
}
1079
1080
@@ -XXX,XX +XXX,XX @@ static void job_clean(Job *job)
1081
}
1082
}
1083
1084
-static int job_finalize_single(Job *job)
1085
+/* Called with job_mutex held, but releases it temporarily */
1086
+static int job_finalize_single_locked(Job *job)
1087
{
1088
- assert(job_is_completed(job));
1089
+ int job_ret;
1090
+
1091
+ assert(job_is_completed_locked(job));
1092
1093
/* Ensure abort is called for late-transactional failures */
1094
- job_update_rc(job);
1095
+ job_update_rc_locked(job);
1096
+
1097
+ job_ret = job->ret;
1098
+ job_unlock();
1099
1100
- if (!job->ret) {
1101
+ if (!job_ret) {
1102
job_commit(job);
1103
} else {
1104
job_abort(job);
1105
}
1106
job_clean(job);
1107
1108
+ job_lock();
1109
+
1110
if (job->cb) {
1111
- job->cb(job->opaque, job->ret);
1112
+ job_ret = job->ret;
1113
+ job_unlock();
1114
+ job->cb(job->opaque, job_ret);
1115
+ job_lock();
1116
}
1117
1118
/* Emit events only if we actually started */
1119
- if (job_started(job)) {
1120
- if (job_is_cancelled(job)) {
1121
- job_event_cancelled(job);
1122
+ if (job_started_locked(job)) {
1123
+ if (job_is_cancelled_locked(job)) {
1124
+ job_event_cancelled_locked(job);
1125
} else {
1126
- job_event_completed(job);
1127
+ job_event_completed_locked(job);
1128
}
1129
}
1130
1131
- job_txn_del_job(job);
1132
- job_conclude(job);
1133
+ job_txn_del_job_locked(job);
1134
+ job_conclude_locked(job);
1135
return 0;
1136
}
1137
1138
-static void job_cancel_async(Job *job, bool force)
1139
+/* Called with job_mutex held, but releases it temporarily */
1140
+static void job_cancel_async_locked(Job *job, bool force)
1141
{
1142
GLOBAL_STATE_CODE();
1143
if (job->driver->cancel) {
1144
+ job_unlock();
1145
force = job->driver->cancel(job, force);
1146
+ job_lock();
1147
} else {
1148
/* No .cancel() means the job will behave as if force-cancelled */
1149
force = true;
1150
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async(Job *job, bool force)
1151
if (job->user_paused) {
1152
/* Do not call job_enter here, the caller will handle it. */
1153
if (job->driver->user_resume) {
1154
+ job_unlock();
1155
job->driver->user_resume(job);
1156
+ job_lock();
1157
}
1158
job->user_paused = false;
1159
assert(job->pause_count > 0);
1160
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async(Job *job, bool force)
1161
}
1162
}
1163
1164
-static void job_completed_txn_abort(Job *job)
1165
+/* Called with job_mutex held, but releases it temporarily. */
1166
+static void job_completed_txn_abort_locked(Job *job)
1167
{
1168
AioContext *ctx;
1169
JobTxn *txn = job->txn;
1170
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
119
return;
1171
return;
120
}
1172
}
121
- ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
1173
txn->aborting = true;
122
+ ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
1174
- job_txn_ref(txn);
123
}
1175
+ job_txn_ref_locked(txn);
124
1176
125
static void mirror_complete(BlockJob *job, Error **errp)
1177
/*
126
diff --git a/block/stream.c b/block/stream.c
1178
* We can only hold the single job's AioContext lock while calling
127
index XXXXXXX..XXXXXXX 100644
1179
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
128
--- a/block/stream.c
1180
* calls of AIO_WAIT_WHILE(), which could deadlock otherwise.
129
+++ b/block/stream.c
1181
* Note that the job's AioContext may change when it is finalized.
130
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
1182
*/
131
/* Publish progress */
1183
- job_ref(job);
132
s->common.offset += n * BDRV_SECTOR_SIZE;
1184
+ job_ref_locked(job);
133
if (copy && s->common.speed) {
1185
aio_context_release(job->aio_context);
134
- delay_ns = ratelimit_calculate_delay(&s->limit, n);
1186
135
+ delay_ns = ratelimit_calculate_delay(&s->limit,
1187
/* Other jobs are effectively cancelled by us, set the status for
136
+ n * BDRV_SECTOR_SIZE);
1188
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1189
* Therefore, pass force=true to terminate all other jobs as quickly
1190
* as possible.
1191
*/
1192
- job_cancel_async(other_job, true);
1193
+ job_cancel_async_locked(other_job, true);
1194
aio_context_release(ctx);
137
}
1195
}
138
}
1196
}
139
1197
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
140
@@ -XXX,XX +XXX,XX @@ static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
1198
*/
141
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
1199
ctx = other_job->aio_context;
1200
aio_context_acquire(ctx);
1201
- if (!job_is_completed(other_job)) {
1202
- assert(job_cancel_requested(other_job));
1203
- job_finish_sync(other_job, NULL, NULL);
1204
+ if (!job_is_completed_locked(other_job)) {
1205
+ assert(job_cancel_requested_locked(other_job));
1206
+ job_finish_sync_locked(other_job, NULL, NULL);
1207
}
1208
- job_finalize_single(other_job);
1209
+ job_finalize_single_locked(other_job);
1210
aio_context_release(ctx);
1211
}
1212
1213
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort(Job *job)
1214
* even if the job went away during job_finalize_single().
1215
*/
1216
aio_context_acquire(job->aio_context);
1217
- job_unref(job);
1218
+ job_unref_locked(job);
1219
1220
- job_txn_unref(txn);
1221
+ job_txn_unref_locked(txn);
1222
}
1223
1224
-static int job_prepare(Job *job)
1225
+/* Called with job_mutex held, but releases it temporarily */
1226
+static int job_prepare_locked(Job *job)
1227
{
1228
+ int ret;
1229
+
1230
GLOBAL_STATE_CODE();
1231
if (job->ret == 0 && job->driver->prepare) {
1232
- job->ret = job->driver->prepare(job);
1233
- job_update_rc(job);
1234
+ job_unlock();
1235
+ ret = job->driver->prepare(job);
1236
+ job_lock();
1237
+ job->ret = ret;
1238
+ job_update_rc_locked(job);
1239
}
1240
return job->ret;
1241
}
1242
1243
-static int job_needs_finalize(Job *job)
1244
+/* Called with job_mutex held */
1245
+static int job_needs_finalize_locked(Job *job)
1246
{
1247
return !job->auto_finalize;
1248
}
1249
1250
-static void job_do_finalize(Job *job)
1251
+/* Called with job_mutex held */
1252
+static void job_do_finalize_locked(Job *job)
1253
{
1254
int rc;
1255
assert(job && job->txn);
1256
1257
/* prepare the transaction to complete */
1258
- rc = job_txn_apply(job, job_prepare);
1259
+ rc = job_txn_apply_locked(job, job_prepare_locked);
1260
if (rc) {
1261
- job_completed_txn_abort(job);
1262
+ job_completed_txn_abort_locked(job);
1263
} else {
1264
- job_txn_apply(job, job_finalize_single);
1265
+ job_txn_apply_locked(job, job_finalize_single_locked);
1266
}
1267
}
1268
1269
-void job_finalize(Job *job, Error **errp)
1270
+void job_finalize_locked(Job *job, Error **errp)
1271
{
1272
assert(job && job->id);
1273
- if (job_apply_verb(job, JOB_VERB_FINALIZE, errp)) {
1274
+ if (job_apply_verb_locked(job, JOB_VERB_FINALIZE, errp)) {
142
return;
1275
return;
143
}
1276
}
144
- ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
1277
- job_do_finalize(job);
145
+ ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
1278
+ job_do_finalize_locked(job);
146
}
1279
}
147
1280
148
static const BlockJobDriver stream_job_driver = {
1281
-static int job_transition_to_pending(Job *job)
149
diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h
1282
+void job_finalize(Job *job, Error **errp)
150
index XXXXXXX..XXXXXXX 100644
1283
{
151
--- a/include/qemu/ratelimit.h
1284
- job_state_transition(job, JOB_STATUS_PENDING);
152
+++ b/include/qemu/ratelimit.h
1285
+ JOB_LOCK_GUARD();
153
@@ -XXX,XX +XXX,XX @@ typedef struct {
1286
+ job_finalize_locked(job, errp);
154
1287
+}
155
/** Calculate and return delay for next request in ns
1288
+
156
*
1289
+/* Called with job_mutex held. */
157
- * Record that we sent @p n data units. If we may send more data units
1290
+static int job_transition_to_pending_locked(Job *job)
158
+ * Record that we sent @n data units (where @n matches the scale chosen
1291
+{
159
+ * during ratelimit_set_speed). If we may send more data units
1292
+ job_state_transition_locked(job, JOB_STATUS_PENDING);
160
* in the current time slice, return 0 (i.e. no delay). Otherwise
1293
if (!job->auto_finalize) {
161
* return the amount of time (in ns) until the start of the next time
1294
- job_event_pending(job);
162
* slice that will permit sending the next chunk of data.
1295
+ job_event_pending_locked(job);
1296
}
1297
return 0;
1298
}
1299
1300
void job_transition_to_ready(Job *job)
1301
{
1302
- job_state_transition(job, JOB_STATUS_READY);
1303
- job_event_ready(job);
1304
+ JOB_LOCK_GUARD();
1305
+ job_state_transition_locked(job, JOB_STATUS_READY);
1306
+ job_event_ready_locked(job);
1307
}
1308
1309
-static void job_completed_txn_success(Job *job)
1310
+/* Called with job_mutex held. */
1311
+static void job_completed_txn_success_locked(Job *job)
1312
{
1313
JobTxn *txn = job->txn;
1314
Job *other_job;
1315
1316
- job_state_transition(job, JOB_STATUS_WAITING);
1317
+ job_state_transition_locked(job, JOB_STATUS_WAITING);
1318
1319
/*
1320
* Successful completion, see if there are other running jobs in this
1321
* txn.
1322
*/
1323
QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
1324
- if (!job_is_completed(other_job)) {
1325
+ if (!job_is_completed_locked(other_job)) {
1326
return;
1327
}
1328
assert(other_job->ret == 0);
1329
}
1330
1331
- job_txn_apply(job, job_transition_to_pending);
1332
+ job_txn_apply_locked(job, job_transition_to_pending_locked);
1333
1334
/* If no jobs need manual finalization, automatically do so */
1335
- if (job_txn_apply(job, job_needs_finalize) == 0) {
1336
- job_do_finalize(job);
1337
+ if (job_txn_apply_locked(job, job_needs_finalize_locked) == 0) {
1338
+ job_do_finalize_locked(job);
1339
}
1340
}
1341
1342
-static void job_completed(Job *job)
1343
+/* Called with job_mutex held. */
1344
+static void job_completed_locked(Job *job)
1345
{
1346
- assert(job && job->txn && !job_is_completed(job));
1347
+ assert(job && job->txn && !job_is_completed_locked(job));
1348
1349
- job_update_rc(job);
1350
+ job_update_rc_locked(job);
1351
trace_job_completed(job, job->ret);
1352
if (job->ret) {
1353
- job_completed_txn_abort(job);
1354
+ job_completed_txn_abort_locked(job);
1355
} else {
1356
- job_completed_txn_success(job);
1357
+ job_completed_txn_success_locked(job);
1358
}
1359
}
1360
1361
-/** Useful only as a type shim for aio_bh_schedule_oneshot. */
1362
+/**
1363
+ * Useful only as a type shim for aio_bh_schedule_oneshot.
1364
+ * Called with job_mutex *not* held.
1365
+ */
1366
static void job_exit(void *opaque)
1367
{
1368
Job *job = (Job *)opaque;
1369
AioContext *ctx;
1370
+ JOB_LOCK_GUARD();
1371
1372
- job_ref(job);
1373
+ job_ref_locked(job);
1374
aio_context_acquire(job->aio_context);
1375
1376
/* This is a lie, we're not quiescent, but still doing the completion
1377
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1378
* drain block nodes, and if .drained_poll still returned true, we would
1379
* deadlock. */
1380
job->busy = false;
1381
- job_event_idle(job);
1382
+ job_event_idle_locked(job);
1383
1384
- job_completed(job);
1385
+ job_completed_locked(job);
1386
1387
/*
1388
* Note that calling job_completed can move the job to a different
1389
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1390
* the job underneath us.
1391
*/
1392
ctx = job->aio_context;
1393
- job_unref(job);
1394
+ job_unref_locked(job);
1395
aio_context_release(ctx);
1396
}
1397
1398
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
1399
static void coroutine_fn job_co_entry(void *opaque)
1400
{
1401
Job *job = opaque;
1402
+ int ret;
1403
1404
assert(job && job->driver && job->driver->run);
1405
- assert(job->aio_context == qemu_get_current_aio_context());
1406
- job_pause_point(job);
1407
- job->ret = job->driver->run(job, &job->err);
1408
- job->deferred_to_main_loop = true;
1409
- job->busy = true;
1410
+ WITH_JOB_LOCK_GUARD() {
1411
+ assert(job->aio_context == qemu_get_current_aio_context());
1412
+ job_pause_point_locked(job);
1413
+ }
1414
+ ret = job->driver->run(job, &job->err);
1415
+ WITH_JOB_LOCK_GUARD() {
1416
+ job->ret = ret;
1417
+ job->deferred_to_main_loop = true;
1418
+ job->busy = true;
1419
+ }
1420
aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job);
1421
}
1422
1423
void job_start(Job *job)
1424
{
1425
- assert(job && !job_started(job) && job->paused &&
1426
- job->driver && job->driver->run);
1427
- job->co = qemu_coroutine_create(job_co_entry, job);
1428
- job->pause_count--;
1429
- job->busy = true;
1430
- job->paused = false;
1431
- job_state_transition(job, JOB_STATUS_RUNNING);
1432
+ assert(qemu_in_main_thread());
1433
+
1434
+ WITH_JOB_LOCK_GUARD() {
1435
+ assert(job && !job_started_locked(job) && job->paused &&
1436
+ job->driver && job->driver->run);
1437
+ job->co = qemu_coroutine_create(job_co_entry, job);
1438
+ job->pause_count--;
1439
+ job->busy = true;
1440
+ job->paused = false;
1441
+ job_state_transition_locked(job, JOB_STATUS_RUNNING);
1442
+ }
1443
aio_co_enter(job->aio_context, job->co);
1444
}
1445
1446
-void job_cancel(Job *job, bool force)
1447
+void job_cancel_locked(Job *job, bool force)
1448
{
1449
if (job->status == JOB_STATUS_CONCLUDED) {
1450
- job_do_dismiss(job);
1451
+ job_do_dismiss_locked(job);
1452
return;
1453
}
1454
- job_cancel_async(job, force);
1455
- if (!job_started(job)) {
1456
- job_completed(job);
1457
+ job_cancel_async_locked(job, force);
1458
+ if (!job_started_locked(job)) {
1459
+ job_completed_locked(job);
1460
} else if (job->deferred_to_main_loop) {
1461
/*
1462
* job_cancel_async() ignores soft-cancel requests for jobs
1463
@@ -XXX,XX +XXX,XX @@ void job_cancel(Job *job, bool force)
1464
* choose to call job_is_cancelled() to show that we invoke
1465
* job_completed_txn_abort() only for force-cancelled jobs.)
1466
*/
1467
- if (job_is_cancelled(job)) {
1468
- job_completed_txn_abort(job);
1469
+ if (job_is_cancelled_locked(job)) {
1470
+ job_completed_txn_abort_locked(job);
1471
}
1472
} else {
1473
- job_enter(job);
1474
+ job_enter_cond_locked(job, NULL);
1475
}
1476
}
1477
1478
-void job_user_cancel(Job *job, bool force, Error **errp)
1479
+void job_cancel(Job *job, bool force)
1480
{
1481
- if (job_apply_verb(job, JOB_VERB_CANCEL, errp)) {
1482
+ JOB_LOCK_GUARD();
1483
+ job_cancel_locked(job, force);
1484
+}
1485
+
1486
+void job_user_cancel_locked(Job *job, bool force, Error **errp)
1487
+{
1488
+ if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) {
1489
return;
1490
}
1491
- job_cancel(job, force);
1492
+ job_cancel_locked(job, force);
1493
+}
1494
+
1495
+void job_user_cancel(Job *job, bool force, Error **errp)
1496
+{
1497
+ JOB_LOCK_GUARD();
1498
+ job_user_cancel_locked(job, force, errp);
1499
}
1500
1501
/* A wrapper around job_cancel() taking an Error ** parameter so it may be
1502
* used with job_finish_sync() without the need for (rather nasty) function
1503
- * pointer casts there. */
1504
-static void job_cancel_err(Job *job, Error **errp)
1505
+ * pointer casts there.
1506
+ *
1507
+ * Called with job_mutex held.
1508
+ */
1509
+static void job_cancel_err_locked(Job *job, Error **errp)
1510
{
1511
- job_cancel(job, false);
1512
+ job_cancel_locked(job, false);
1513
}
1514
1515
/**
1516
* Same as job_cancel_err(), but force-cancel.
1517
+ * Called with job_mutex held.
1518
*/
1519
-static void job_force_cancel_err(Job *job, Error **errp)
1520
+static void job_force_cancel_err_locked(Job *job, Error **errp)
1521
{
1522
- job_cancel(job, true);
1523
+ job_cancel_locked(job, true);
1524
}
1525
1526
-int job_cancel_sync(Job *job, bool force)
1527
+int job_cancel_sync_locked(Job *job, bool force)
1528
{
1529
if (force) {
1530
- return job_finish_sync(job, &job_force_cancel_err, NULL);
1531
+ return job_finish_sync_locked(job, &job_force_cancel_err_locked, NULL);
1532
} else {
1533
- return job_finish_sync(job, &job_cancel_err, NULL);
1534
+ return job_finish_sync_locked(job, &job_cancel_err_locked, NULL);
1535
}
1536
}
1537
1538
+int job_cancel_sync(Job *job, bool force)
1539
+{
1540
+ JOB_LOCK_GUARD();
1541
+ return job_cancel_sync_locked(job, force);
1542
+}
1543
+
1544
void job_cancel_sync_all(void)
1545
{
1546
Job *job;
1547
AioContext *aio_context;
1548
+ JOB_LOCK_GUARD();
1549
1550
- while ((job = job_next(NULL))) {
1551
+ while ((job = job_next_locked(NULL))) {
1552
aio_context = job->aio_context;
1553
aio_context_acquire(aio_context);
1554
- job_cancel_sync(job, true);
1555
+ job_cancel_sync_locked(job, true);
1556
aio_context_release(aio_context);
1557
}
1558
}
1559
1560
+int job_complete_sync_locked(Job *job, Error **errp)
1561
+{
1562
+ return job_finish_sync_locked(job, job_complete_locked, errp);
1563
+}
1564
+
1565
int job_complete_sync(Job *job, Error **errp)
1566
{
1567
- return job_finish_sync(job, job_complete, errp);
1568
+ JOB_LOCK_GUARD();
1569
+ return job_complete_sync_locked(job, errp);
1570
}
1571
1572
-void job_complete(Job *job, Error **errp)
1573
+void job_complete_locked(Job *job, Error **errp)
1574
{
1575
/* Should not be reachable via external interface for internal jobs */
1576
assert(job->id);
1577
GLOBAL_STATE_CODE();
1578
- if (job_apply_verb(job, JOB_VERB_COMPLETE, errp)) {
1579
+ if (job_apply_verb_locked(job, JOB_VERB_COMPLETE, errp)) {
1580
return;
1581
}
1582
- if (job_cancel_requested(job) || !job->driver->complete) {
1583
+ if (job_cancel_requested_locked(job) || !job->driver->complete) {
1584
error_setg(errp, "The active block job '%s' cannot be completed",
1585
job->id);
1586
return;
1587
}
1588
1589
+ job_unlock();
1590
job->driver->complete(job, errp);
1591
+ job_lock();
1592
}
1593
1594
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
1595
+void job_complete(Job *job, Error **errp)
1596
+{
1597
+ JOB_LOCK_GUARD();
1598
+ job_complete_locked(job, errp);
1599
+}
1600
+
1601
+int job_finish_sync_locked(Job *job,
1602
+ void (*finish)(Job *, Error **errp),
1603
+ Error **errp)
1604
{
1605
Error *local_err = NULL;
1606
int ret;
1607
1608
- job_ref(job);
1609
+ job_ref_locked(job);
1610
1611
if (finish) {
1612
finish(job, &local_err);
1613
}
1614
if (local_err) {
1615
error_propagate(errp, local_err);
1616
- job_unref(job);
1617
+ job_unref_locked(job);
1618
return -EBUSY;
1619
}
1620
1621
+ job_unlock();
1622
AIO_WAIT_WHILE(job->aio_context,
1623
(job_enter(job), !job_is_completed(job)));
1624
+ job_lock();
1625
1626
- ret = (job_is_cancelled(job) && job->ret == 0) ? -ECANCELED : job->ret;
1627
- job_unref(job);
1628
+ ret = (job_is_cancelled_locked(job) && job->ret == 0)
1629
+ ? -ECANCELED : job->ret;
1630
+ job_unref_locked(job);
1631
return ret;
1632
}
1633
+
1634
+int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
1635
+{
1636
+ JOB_LOCK_GUARD();
1637
+ return job_finish_sync_locked(job, finish, errp);
1638
+}
163
--
1639
--
164
1.8.3.1
1640
2.37.3
165
166
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The block/crypto.c defines a set of QemuOpts that provide
3
This comment applies more on job, it was left in blockjob as in the past
4
parameters for encryption. This will also be needed by
4
the whole job logic was implemented there.
5
the qcow/qcow2 integration, so expose the relevant pieces
6
in a new block/crypto.h header. Some helper methods taking
7
QemuOpts are changed to take QDict to simplify usage in
8
other places.
9
5
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Note: at this stage, job_{lock/unlock} and job lock guard macros
11
Reviewed-by: Eric Blake <eblake@redhat.com>
7
are *nop*.
12
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
13
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
No functional change intended.
14
Message-id: 20170623162419.26068-2-berrange@redhat.com
10
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20220926093214.506243-7-eesposit@redhat.com>
15
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
---
17
block/crypto.c | 82 +++++++++++++++++-----------------------------------
18
blockjob.c | 20 --------------------
18
block/crypto.h | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19
job.c | 16 ++++++++++++++++
19
2 files changed, 117 insertions(+), 56 deletions(-)
20
2 files changed, 16 insertions(+), 20 deletions(-)
20
create mode 100644 block/crypto.h
21
21
22
diff --git a/block/crypto.c b/block/crypto.c
22
diff --git a/blockjob.c b/blockjob.c
23
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/crypto.c
24
--- a/blockjob.c
25
+++ b/block/crypto.c
25
+++ b/blockjob.c
26
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
27
#include "sysemu/block-backend.h"
27
#include "qemu/main-loop.h"
28
#include "crypto/block.h"
28
#include "qemu/timer.h"
29
#include "qapi/opts-visitor.h"
29
30
+#include "qapi/qobject-input-visitor.h"
30
-/*
31
#include "qapi-visit.h"
31
- * The block job API is composed of two categories of functions.
32
#include "qapi/error.h"
32
- *
33
- * The first includes functions used by the monitor. The monitor is
34
- * peculiar in that it accesses the block job list with block_job_get, and
35
- * therefore needs consistency across block_job_get and the actual operation
36
- * (e.g. block_job_set_speed). The consistency is achieved with
37
- * aio_context_acquire/release. These functions are declared in blockjob.h.
38
- *
39
- * The second includes functions used by the block job drivers and sometimes
40
- * by the core block layer. These do not care about locking, because the
41
- * whole coroutine runs under the AioContext lock, and are declared in
42
- * blockjob_int.h.
43
- */
33
-
44
-
34
-#define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
45
static bool is_block_job(Job *job)
35
-#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
36
-#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
37
-#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
38
-#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
39
-#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
40
-#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
41
+#include "block/crypto.h"
42
43
typedef struct BlockCrypto BlockCrypto;
44
45
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_runtime_opts_luks = {
46
.name = "crypto",
47
.head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
48
.desc = {
49
- {
50
- .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
51
- .type = QEMU_OPT_STRING,
52
- .help = "ID of the secret that provides the encryption key",
53
- },
54
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
55
{ /* end of list */ }
56
},
57
};
58
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_create_opts_luks = {
59
.type = QEMU_OPT_SIZE,
60
.help = "Virtual disk size"
61
},
62
- {
63
- .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
64
- .type = QEMU_OPT_STRING,
65
- .help = "ID of the secret that provides the encryption key",
66
- },
67
- {
68
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG,
69
- .type = QEMU_OPT_STRING,
70
- .help = "Name of encryption cipher algorithm",
71
- },
72
- {
73
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE,
74
- .type = QEMU_OPT_STRING,
75
- .help = "Name of encryption cipher mode",
76
- },
77
- {
78
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG,
79
- .type = QEMU_OPT_STRING,
80
- .help = "Name of IV generator algorithm",
81
- },
82
- {
83
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG,
84
- .type = QEMU_OPT_STRING,
85
- .help = "Name of IV generator hash algorithm",
86
- },
87
- {
88
- .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG,
89
- .type = QEMU_OPT_STRING,
90
- .help = "Name of encryption hash algorithm",
91
- },
92
- {
93
- .name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME,
94
- .type = QEMU_OPT_NUMBER,
95
- .help = "Time to spend in PBKDF in milliseconds",
96
- },
97
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
98
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG,
99
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE,
100
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG,
101
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG,
102
+ BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG,
103
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME,
104
{ /* end of list */ }
105
},
106
};
107
108
109
-static QCryptoBlockOpenOptions *
110
+QCryptoBlockOpenOptions *
111
block_crypto_open_opts_init(QCryptoBlockFormat format,
112
- QemuOpts *opts,
113
+ QDict *opts,
114
Error **errp)
115
{
46
{
116
Visitor *v;
47
return job_type(job) == JOB_TYPE_BACKUP ||
117
@@ -XXX,XX +XXX,XX @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
48
@@ -XXX,XX +XXX,XX @@ static void block_job_event_ready(Notifier *n, void *opaque)
118
ret = g_new0(QCryptoBlockOpenOptions, 1);
119
ret->format = format;
120
121
- v = opts_visitor_new(opts);
122
+ v = qobject_input_visitor_new_keyval(QOBJECT(opts));
123
124
visit_start_struct(v, NULL, NULL, 0, &local_err);
125
if (local_err) {
126
@@ -XXX,XX +XXX,XX @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
127
}
49
}
128
50
129
51
130
-static QCryptoBlockCreateOptions *
52
-/*
131
+QCryptoBlockCreateOptions *
53
- * API for block job drivers and the block layer. These functions are
132
block_crypto_create_opts_init(QCryptoBlockFormat format,
54
- * declared in blockjob_int.h.
133
- QemuOpts *opts,
55
- */
134
+ QDict *opts,
56
-
135
Error **errp)
57
void *block_job_create(const char *job_id, const BlockJobDriver *driver,
136
{
58
JobTxn *txn, BlockDriverState *bs, uint64_t perm,
137
Visitor *v;
59
uint64_t shared_perm, int64_t speed, int flags,
138
@@ -XXX,XX +XXX,XX @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
60
diff --git a/job.c b/job.c
139
ret = g_new0(QCryptoBlockCreateOptions, 1);
61
index XXXXXXX..XXXXXXX 100644
140
ret->format = format;
62
--- a/job.c
141
63
+++ b/job.c
142
- v = opts_visitor_new(opts);
143
+ v = qobject_input_visitor_new_keyval(QOBJECT(opts));
144
145
visit_start_struct(v, NULL, NULL, 0, &local_err);
146
if (local_err) {
147
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
148
int ret = -EINVAL;
149
QCryptoBlockOpenOptions *open_opts = NULL;
150
unsigned int cflags = 0;
151
+ QDict *cryptoopts = NULL;
152
153
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
154
false, errp);
155
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
156
goto cleanup;
157
}
158
159
- open_opts = block_crypto_open_opts_init(format, opts, errp);
160
+ cryptoopts = qemu_opts_to_qdict(opts, NULL);
161
+
162
+ open_opts = block_crypto_open_opts_init(format, cryptoopts, errp);
163
if (!open_opts) {
164
goto cleanup;
165
}
166
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
167
168
ret = 0;
169
cleanup:
170
+ QDECREF(cryptoopts);
171
qapi_free_QCryptoBlockOpenOptions(open_opts);
172
return ret;
173
}
174
@@ -XXX,XX +XXX,XX @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
175
.opts = opts,
176
.filename = filename,
177
};
178
+ QDict *cryptoopts;
179
+
180
+ cryptoopts = qemu_opts_to_qdict(opts, NULL);
181
182
- create_opts = block_crypto_create_opts_init(format, opts, errp);
183
+ create_opts = block_crypto_create_opts_init(format, cryptoopts, errp);
184
if (!create_opts) {
185
return -1;
186
}
187
@@ -XXX,XX +XXX,XX @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
188
189
ret = 0;
190
cleanup:
191
+ QDECREF(cryptoopts);
192
qcrypto_block_free(crypto);
193
blk_unref(data.blk);
194
qapi_free_QCryptoBlockCreateOptions(create_opts);
195
diff --git a/block/crypto.h b/block/crypto.h
196
new file mode 100644
197
index XXXXXXX..XXXXXXX
198
--- /dev/null
199
+++ b/block/crypto.h
200
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
65
#include "trace/trace-root.h"
66
#include "qapi/qapi-events-job.h"
67
201
+/*
68
+/*
202
+ * QEMU block full disk encryption
69
+ * The job API is composed of two categories of functions.
203
+ *
70
+ *
204
+ * Copyright (c) 2015-2017 Red Hat, Inc.
71
+ * The first includes functions used by the monitor. The monitor is
72
+ * peculiar in that it accesses the job list with job_get, and
73
+ * therefore needs consistency across job_get and the actual operation
74
+ * (e.g. job_user_cancel). To achieve this consistency, the caller
75
+ * calls job_lock/job_unlock itself around the whole operation.
205
+ *
76
+ *
206
+ * This library is free software; you can redistribute it and/or
207
+ * modify it under the terms of the GNU Lesser General Public
208
+ * License as published by the Free Software Foundation; either
209
+ * version 2 of the License, or (at your option) any later version.
210
+ *
77
+ *
211
+ * This library is distributed in the hope that it will be useful,
78
+ * The second includes functions used by the job drivers and sometimes
212
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
79
+ * by the core block layer. These delegate the locking to the callee instead.
213
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
214
+ * Lesser General Public License for more details.
215
+ *
80
+ *
216
+ * You should have received a copy of the GNU Lesser General Public
81
+ * TODO Actually make this true
217
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
218
+ *
219
+ */
82
+ */
220
+
83
+
221
+#ifndef BLOCK_CRYPTO_H__
84
/*
222
+#define BLOCK_CRYPTO_H__
85
* job_mutex protects the jobs list, but also makes the
223
+
86
* struct job fields thread-safe.
224
+#define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
225
+#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
226
+#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
227
+#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
228
+#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
229
+#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
230
+#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
231
+
232
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET \
233
+ { \
234
+ .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
235
+ .type = QEMU_OPT_STRING, \
236
+ .help = "ID of the secret that provides the keyslot passphrase", \
237
+ }
238
+
239
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG \
240
+ { \
241
+ .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \
242
+ .type = QEMU_OPT_STRING, \
243
+ .help = "Name of encryption cipher algorithm", \
244
+ }
245
+
246
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE \
247
+ { \
248
+ .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \
249
+ .type = QEMU_OPT_STRING, \
250
+ .help = "Name of encryption cipher mode", \
251
+ }
252
+
253
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG \
254
+ { \
255
+ .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \
256
+ .type = QEMU_OPT_STRING, \
257
+ .help = "Name of IV generator algorithm", \
258
+ }
259
+
260
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG \
261
+ { \
262
+ .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \
263
+ .type = QEMU_OPT_STRING, \
264
+ .help = "Name of IV generator hash algorithm", \
265
+ }
266
+
267
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG \
268
+ { \
269
+ .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \
270
+ .type = QEMU_OPT_STRING, \
271
+ .help = "Name of encryption hash algorithm", \
272
+ }
273
+
274
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME \
275
+ { \
276
+ .name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \
277
+ .type = QEMU_OPT_NUMBER, \
278
+ .help = "Time to spend in PBKDF in milliseconds", \
279
+ }
280
+
281
+QCryptoBlockCreateOptions *
282
+block_crypto_create_opts_init(QCryptoBlockFormat format,
283
+ QDict *opts,
284
+ Error **errp);
285
+
286
+QCryptoBlockOpenOptions *
287
+block_crypto_open_opts_init(QCryptoBlockFormat format,
288
+ QDict *opts,
289
+ Error **errp);
290
+
291
+#endif /* BLOCK_CRYPTO_H__ */
292
--
87
--
293
1.8.3.1
88
2.37.3
294
295
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Realize .bdrv_remove_persistent_dirty_bitmap interface.
3
Just as done with job.h, create _locked() functions in blockjob.h
4
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
These functions will be later useful when caller has already taken
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
the lock. All blockjob _locked functions call job _locked functions.
7
Reviewed-by: John Snow <jsnow@redhat.com>
7
8
Message-id: 20170628120530.31251-29-vsementsov@virtuozzo.com
8
Note: at this stage, job_{lock/unlock} and job lock guard macros
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
are *nop*.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-Id: <20220926093214.506243-8-eesposit@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
17
---
11
block/qcow2-bitmap.c | 41 +++++++++++++++++++++++++++++++++++++++++
18
include/block/blockjob.h | 18 ++++++++++++++
12
block/qcow2.c | 1 +
19
blockjob.c | 52 ++++++++++++++++++++++++++++++++--------
13
block/qcow2.h | 3 +++
20
2 files changed, 60 insertions(+), 10 deletions(-)
14
3 files changed, 45 insertions(+)
21
15
22
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
16
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-bitmap.c
24
--- a/include/block/blockjob.h
19
+++ b/block/qcow2-bitmap.c
25
+++ b/include/block/blockjob.h
20
@@ -XXX,XX +XXX,XX @@ static Qcow2Bitmap *find_bitmap_by_name(Qcow2BitmapList *bm_list,
26
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
27
*/
28
BlockJob *block_job_next(BlockJob *job);
29
30
+/* Same as block_job_next(), but called with job lock held. */
31
+BlockJob *block_job_next_locked(BlockJob *job);
32
+
33
/**
34
* block_job_get:
35
* @id: The id of the block job.
36
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next(BlockJob *job);
37
*/
38
BlockJob *block_job_get(const char *id);
39
40
+/* Same as block_job_get(), but called with job lock held. */
41
+BlockJob *block_job_get_locked(const char *id);
42
+
43
/**
44
* block_job_add_bdrv:
45
* @job: A block job
46
@@ -XXX,XX +XXX,XX @@ bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
47
*/
48
bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
49
50
+/*
51
+ * Same as block_job_set_speed(), but called with job lock held.
52
+ * Might release the lock temporarily.
53
+ */
54
+bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
55
+
56
/**
57
* block_job_query:
58
* @job: The job to get information about.
59
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
60
*/
61
BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
62
63
+/* Same as block_job_query(), but called with job lock held. */
64
+BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
65
+
66
/**
67
* block_job_iostatus_reset:
68
* @job: The job whose I/O status should be reset.
69
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
70
*/
71
void block_job_iostatus_reset(BlockJob *job);
72
73
+/* Same as block_job_iostatus_reset(), but called with job lock held. */
74
+void block_job_iostatus_reset_locked(BlockJob *job);
75
+
76
/*
77
* block_job_get_aio_context:
78
*
79
diff --git a/blockjob.c b/blockjob.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/blockjob.c
82
+++ b/blockjob.c
83
@@ -XXX,XX +XXX,XX @@ static bool is_block_job(Job *job)
84
job_type(job) == JOB_TYPE_STREAM;
85
}
86
87
-BlockJob *block_job_next(BlockJob *bjob)
88
+BlockJob *block_job_next_locked(BlockJob *bjob)
89
{
90
Job *job = bjob ? &bjob->job : NULL;
91
GLOBAL_STATE_CODE();
92
93
do {
94
- job = job_next(job);
95
+ job = job_next_locked(job);
96
} while (job && !is_block_job(job));
97
98
return job ? container_of(job, BlockJob, job) : NULL;
99
}
100
101
-BlockJob *block_job_get(const char *id)
102
+BlockJob *block_job_next(BlockJob *bjob)
103
{
104
- Job *job = job_get(id);
105
+ JOB_LOCK_GUARD();
106
+ return block_job_next_locked(bjob);
107
+}
108
+
109
+BlockJob *block_job_get_locked(const char *id)
110
+{
111
+ Job *job = job_get_locked(id);
112
GLOBAL_STATE_CODE();
113
114
if (job && is_block_job(job)) {
115
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_get(const char *id)
116
}
117
}
118
119
+BlockJob *block_job_get(const char *id)
120
+{
121
+ JOB_LOCK_GUARD();
122
+ return block_job_get_locked(id);
123
+}
124
+
125
void block_job_free(Job *job)
126
{
127
BlockJob *bjob = container_of(job, BlockJob, job);
128
@@ -XXX,XX +XXX,XX @@ static bool job_timer_pending(Job *job)
129
return timer_pending(&job->sleep_timer);
130
}
131
132
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
133
+bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp)
134
{
135
const BlockJobDriver *drv = block_job_driver(job);
136
int64_t old_speed = job->speed;
137
138
GLOBAL_STATE_CODE();
139
140
- if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp) < 0) {
141
+ if (job_apply_verb_locked(&job->job, JOB_VERB_SET_SPEED, errp) < 0) {
142
return false;
143
}
144
if (speed < 0) {
145
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
146
job->speed = speed;
147
148
if (drv->set_speed) {
149
+ job_unlock();
150
drv->set_speed(job, speed);
151
+ job_lock();
152
}
153
154
if (speed && speed <= old_speed) {
155
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
156
}
157
158
/* kick only if a timer is pending */
159
- job_enter_cond(&job->job, job_timer_pending);
160
+ job_enter_cond_locked(&job->job, job_timer_pending);
161
162
return true;
163
}
164
165
+bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
166
+{
167
+ JOB_LOCK_GUARD();
168
+ return block_job_set_speed_locked(job, speed, errp);
169
+}
170
+
171
int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
172
{
173
IO_CODE();
174
return ratelimit_calculate_delay(&job->limit, n);
175
}
176
177
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
178
+BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
179
{
180
BlockJobInfo *info;
181
uint64_t progress_current, progress_total;
182
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
183
info->len = progress_total;
184
info->speed = job->speed;
185
info->io_status = job->iostatus;
186
- info->ready = job_is_ready(&job->job),
187
+ info->ready = job_is_ready_locked(&job->job),
188
info->status = job->job.status;
189
info->auto_finalize = job->job.auto_finalize;
190
info->auto_dismiss = job->job.auto_dismiss;
191
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
192
return info;
193
}
194
195
+BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
196
+{
197
+ JOB_LOCK_GUARD();
198
+ return block_job_query_locked(job, errp);
199
+}
200
+
201
static void block_job_iostatus_set_err(BlockJob *job, int error)
202
{
203
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
204
@@ -XXX,XX +XXX,XX @@ fail:
21
return NULL;
205
return NULL;
22
}
206
}
23
207
24
+void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
208
-void block_job_iostatus_reset(BlockJob *job)
25
+ const char *name,
209
+void block_job_iostatus_reset_locked(BlockJob *job)
26
+ Error **errp)
210
{
27
+{
211
GLOBAL_STATE_CODE();
28
+ int ret;
212
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
29
+ BDRVQcow2State *s = bs->opaque;
213
@@ -XXX,XX +XXX,XX @@ void block_job_iostatus_reset(BlockJob *job)
30
+ Qcow2Bitmap *bm;
214
job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
31
+ Qcow2BitmapList *bm_list;
215
}
32
+
216
33
+ if (s->nb_bitmaps == 0) {
217
+void block_job_iostatus_reset(BlockJob *job)
34
+ /* Absence of the bitmap is not an error: see explanation above
218
+{
35
+ * bdrv_remove_persistent_dirty_bitmap() definition. */
219
+ JOB_LOCK_GUARD();
36
+ return;
220
+ block_job_iostatus_reset_locked(job);
37
+ }
221
+}
38
+
222
+
39
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
223
void block_job_user_resume(Job *job)
40
+ s->bitmap_directory_size, errp);
224
{
41
+ if (bm_list == NULL) {
225
BlockJob *bjob = container_of(job, BlockJob, job);
42
+ return;
43
+ }
44
+
45
+ bm = find_bitmap_by_name(bm_list, name);
46
+ if (bm == NULL) {
47
+ goto fail;
48
+ }
49
+
50
+ QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry);
51
+
52
+ ret = update_ext_header_and_dir(bs, bm_list);
53
+ if (ret < 0) {
54
+ error_setg_errno(errp, -ret, "Failed to update bitmap extension");
55
+ goto fail;
56
+ }
57
+
58
+ free_bitmap_clusters(bs, &bm->table);
59
+
60
+fail:
61
+ bitmap_free(bm);
62
+ bitmap_list_free(bm_list);
63
+}
64
+
65
void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
66
{
67
BdrvDirtyBitmap *bitmap;
68
diff --git a/block/qcow2.c b/block/qcow2.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/qcow2.c
71
+++ b/block/qcow2.c
72
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
73
74
.bdrv_reopen_bitmaps_rw = qcow2_reopen_bitmaps_rw,
75
.bdrv_can_store_new_dirty_bitmap = qcow2_can_store_new_dirty_bitmap,
76
+ .bdrv_remove_persistent_dirty_bitmap = qcow2_remove_persistent_dirty_bitmap,
77
};
78
79
static void bdrv_qcow2_init(void)
80
diff --git a/block/qcow2.h b/block/qcow2.h
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/qcow2.h
83
+++ b/block/qcow2.h
84
@@ -XXX,XX +XXX,XX @@ bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
85
const char *name,
86
uint32_t granularity,
87
Error **errp);
88
+void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
89
+ const char *name,
90
+ Error **errp);
91
92
#endif
93
--
226
--
94
1.8.3.1
227
2.37.3
95
96
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We likely do not want to carry these legacy -drive options along forever.
3
Both blockdev.c and job-qmp.c have TOC/TOU conditions, because
4
Let's emit a deprecation warning for the -drive options that have a
4
they first search for the job and then perform an action on it.
5
replacement with the -device option, so that the (hopefully few) remaining
5
Therefore, we need to do the search + action under the same
6
users are aware of this and can adapt their scripts / behaviour accordingly.
6
job mutex critical section.
7
7
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Note: at this stage, job_{lock/unlock} and job lock guard macros
9
Reviewed-by: Markus Armbruster <armbru@redhat.com>
9
are *nop*.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20220926093214.506243-9-eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
17
---
12
blockdev.c | 14 ++++++++++++++
18
blockdev.c | 67 +++++++++++++++++++++++++++++++++++++-----------------
13
qemu-options.hx | 9 +++++++--
19
job-qmp.c | 57 ++++++++++++++++++++++++++++++++--------------
14
2 files changed, 21 insertions(+), 2 deletions(-)
20
2 files changed, 86 insertions(+), 38 deletions(-)
15
21
16
diff --git a/blockdev.c b/blockdev.c
22
diff --git a/blockdev.c b/blockdev.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/blockdev.c
24
--- a/blockdev.c
19
+++ b/blockdev.c
25
+++ b/blockdev.c
26
@@ -XXX,XX +XXX,XX @@ out:
27
aio_context_release(aio_context);
28
}
29
30
-/* Get a block job using its ID and acquire its AioContext */
31
-static BlockJob *find_block_job(const char *id, AioContext **aio_context,
32
- Error **errp)
33
+/*
34
+ * Get a block job using its ID and acquire its AioContext.
35
+ * Called with job_mutex held.
36
+ */
37
+static BlockJob *find_block_job_locked(const char *id,
38
+ AioContext **aio_context,
39
+ Error **errp)
40
{
41
BlockJob *job;
42
43
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context,
44
45
*aio_context = NULL;
46
47
- job = block_job_get(id);
48
+ job = block_job_get_locked(id);
49
50
if (!job) {
51
error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
52
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context,
53
void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
54
{
55
AioContext *aio_context;
56
- BlockJob *job = find_block_job(device, &aio_context, errp);
57
+ BlockJob *job;
58
+
59
+ JOB_LOCK_GUARD();
60
+ job = find_block_job_locked(device, &aio_context, errp);
61
62
if (!job) {
63
return;
64
}
65
66
- block_job_set_speed(job, speed, errp);
67
+ block_job_set_speed_locked(job, speed, errp);
68
aio_context_release(aio_context);
69
}
70
71
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
72
bool has_force, bool force, Error **errp)
73
{
74
AioContext *aio_context;
75
- BlockJob *job = find_block_job(device, &aio_context, errp);
76
+ BlockJob *job;
77
+
78
+ JOB_LOCK_GUARD();
79
+ job = find_block_job_locked(device, &aio_context, errp);
80
81
if (!job) {
82
return;
83
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
84
force = false;
85
}
86
87
- if (job_user_paused(&job->job) && !force) {
88
+ if (job_user_paused_locked(&job->job) && !force) {
89
error_setg(errp, "The block job for device '%s' is currently paused",
90
device);
91
goto out;
92
}
93
94
trace_qmp_block_job_cancel(job);
95
- job_user_cancel(&job->job, force, errp);
96
+ job_user_cancel_locked(&job->job, force, errp);
97
out:
98
aio_context_release(aio_context);
99
}
100
@@ -XXX,XX +XXX,XX @@ out:
101
void qmp_block_job_pause(const char *device, Error **errp)
102
{
103
AioContext *aio_context;
104
- BlockJob *job = find_block_job(device, &aio_context, errp);
105
+ BlockJob *job;
106
+
107
+ JOB_LOCK_GUARD();
108
+ job = find_block_job_locked(device, &aio_context, errp);
109
110
if (!job) {
111
return;
112
}
113
114
trace_qmp_block_job_pause(job);
115
- job_user_pause(&job->job, errp);
116
+ job_user_pause_locked(&job->job, errp);
117
aio_context_release(aio_context);
118
}
119
120
void qmp_block_job_resume(const char *device, Error **errp)
121
{
122
AioContext *aio_context;
123
- BlockJob *job = find_block_job(device, &aio_context, errp);
124
+ BlockJob *job;
125
+
126
+ JOB_LOCK_GUARD();
127
+ job = find_block_job_locked(device, &aio_context, errp);
128
129
if (!job) {
130
return;
131
}
132
133
trace_qmp_block_job_resume(job);
134
- job_user_resume(&job->job, errp);
135
+ job_user_resume_locked(&job->job, errp);
136
aio_context_release(aio_context);
137
}
138
139
void qmp_block_job_complete(const char *device, Error **errp)
140
{
141
AioContext *aio_context;
142
- BlockJob *job = find_block_job(device, &aio_context, errp);
143
+ BlockJob *job;
144
+
145
+ JOB_LOCK_GUARD();
146
+ job = find_block_job_locked(device, &aio_context, errp);
147
148
if (!job) {
149
return;
150
}
151
152
trace_qmp_block_job_complete(job);
153
- job_complete(&job->job, errp);
154
+ job_complete_locked(&job->job, errp);
155
aio_context_release(aio_context);
156
}
157
158
void qmp_block_job_finalize(const char *id, Error **errp)
159
{
160
AioContext *aio_context;
161
- BlockJob *job = find_block_job(id, &aio_context, errp);
162
+ BlockJob *job;
163
+
164
+ JOB_LOCK_GUARD();
165
+ job = find_block_job_locked(id, &aio_context, errp);
166
167
if (!job) {
168
return;
169
}
170
171
trace_qmp_block_job_finalize(job);
172
- job_ref(&job->job);
173
- job_finalize(&job->job, errp);
174
+ job_ref_locked(&job->job);
175
+ job_finalize_locked(&job->job, errp);
176
177
/*
178
* Job's context might have changed via job_finalize (and job_txn_apply
179
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_finalize(const char *id, Error **errp)
180
* one.
181
*/
182
aio_context = block_job_get_aio_context(job);
183
- job_unref(&job->job);
184
+ job_unref_locked(&job->job);
185
aio_context_release(aio_context);
186
}
187
188
void qmp_block_job_dismiss(const char *id, Error **errp)
189
{
190
AioContext *aio_context;
191
- BlockJob *bjob = find_block_job(id, &aio_context, errp);
192
+ BlockJob *bjob;
193
Job *job;
194
195
+ JOB_LOCK_GUARD();
196
+ bjob = find_block_job_locked(id, &aio_context, errp);
197
+
198
if (!bjob) {
199
return;
200
}
201
202
trace_qmp_block_job_dismiss(bjob);
203
job = &bjob->job;
204
- job_dismiss(&job, errp);
205
+ job_dismiss_locked(&job, errp);
206
aio_context_release(aio_context);
207
}
208
209
diff --git a/job-qmp.c b/job-qmp.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/job-qmp.c
212
+++ b/job-qmp.c
20
@@ -XXX,XX +XXX,XX @@
213
@@ -XXX,XX +XXX,XX @@
21
#include "qmp-commands.h"
214
#include "qapi/error.h"
22
#include "block/trace.h"
215
#include "trace/trace-root.h"
23
#include "sysemu/arch_init.h"
216
24
+#include "sysemu/qtest.h"
217
-/* Get a job using its ID and acquire its AioContext */
25
#include "qemu/cutils.h"
218
-static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
26
#include "qemu/help_option.h"
219
+/*
27
#include "qemu/throttle-options.h"
220
+ * Get a job using its ID and acquire its AioContext.
28
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
221
+ * Called with job_mutex held.
29
const char *filename;
222
+ */
30
Error *local_err = NULL;
223
+static Job *find_job_locked(const char *id,
31
int i;
224
+ AioContext **aio_context,
32
+ const char *deprecated[] = {
225
+ Error **errp)
33
+ "serial", "trans", "secs", "heads", "cyls", "addr"
226
{
34
+ };
227
Job *job;
35
228
36
/* Change legacy command line options into QMP ones */
229
*aio_context = NULL;
37
static const struct {
230
38
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
231
- job = job_get(id);
39
"update your scripts.\n");
232
+ job = job_get_locked(id);
40
}
233
if (!job) {
41
234
error_setg(errp, "Job not found");
42
+ /* Other deprecated options */
235
return NULL;
43
+ if (!qtest_enabled()) {
236
@@ -XXX,XX +XXX,XX @@ static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
44
+ for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
237
void qmp_job_cancel(const char *id, Error **errp)
45
+ if (qemu_opt_get(legacy_opts, deprecated[i]) != NULL) {
238
{
46
+ error_report("'%s' is deprecated, please use the corresponding "
239
AioContext *aio_context;
47
+ "option of '-device' instead", deprecated[i]);
240
- Job *job = find_job(id, &aio_context, errp);
48
+ }
241
+ Job *job;
49
+ }
242
+
50
+ }
243
+ JOB_LOCK_GUARD();
51
+
244
+ job = find_job_locked(id, &aio_context, errp);
52
/* Media type */
245
53
value = qemu_opt_get(legacy_opts, "media");
246
if (!job) {
54
if (value) {
247
return;
55
diff --git a/qemu-options.hx b/qemu-options.hx
248
}
56
index XXXXXXX..XXXXXXX 100644
249
57
--- a/qemu-options.hx
250
trace_qmp_job_cancel(job);
58
+++ b/qemu-options.hx
251
- job_user_cancel(job, true, errp);
59
@@ -XXX,XX +XXX,XX @@ of available connectors of a given interface type.
252
+ job_user_cancel_locked(job, true, errp);
60
This option defines the type of the media: disk or cdrom.
253
aio_context_release(aio_context);
61
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
254
}
62
These options have the same definition as they have in @option{-hdachs}.
255
63
+These parameters are deprecated, use the corresponding parameters
256
void qmp_job_pause(const char *id, Error **errp)
64
+of @code{-device} instead.
257
{
65
@item snapshot=@var{snapshot}
258
AioContext *aio_context;
66
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
259
- Job *job = find_job(id, &aio_context, errp);
67
(see @option{-snapshot}).
260
+ Job *job;
68
@@ -XXX,XX +XXX,XX @@ Specify which disk @var{format} will be used rather than detecting
261
+
69
the format. Can be used to specify format=raw to avoid interpreting
262
+ JOB_LOCK_GUARD();
70
an untrusted format header.
263
+ job = find_job_locked(id, &aio_context, errp);
71
@item serial=@var{serial}
264
72
-This option specifies the serial number to assign to the device.
265
if (!job) {
73
+This option specifies the serial number to assign to the device. This
266
return;
74
+parameter is deprecated, use the corresponding parameter of @code{-device}
267
}
75
+instead.
268
76
@item addr=@var{addr}
269
trace_qmp_job_pause(job);
77
-Specify the controller's PCI address (if=virtio only).
270
- job_user_pause(job, errp);
78
+Specify the controller's PCI address (if=virtio only). This parameter is
271
+ job_user_pause_locked(job, errp);
79
+deprecated, use the corresponding parameter of @code{-device} instead.
272
aio_context_release(aio_context);
80
@item werror=@var{action},rerror=@var{action}
273
}
81
Specify which @var{action} to take on write and read errors. Valid actions are:
274
82
"ignore" (ignore the error and try to continue), "stop" (pause QEMU),
275
void qmp_job_resume(const char *id, Error **errp)
276
{
277
AioContext *aio_context;
278
- Job *job = find_job(id, &aio_context, errp);
279
+ Job *job;
280
+
281
+ JOB_LOCK_GUARD();
282
+ job = find_job_locked(id, &aio_context, errp);
283
284
if (!job) {
285
return;
286
}
287
288
trace_qmp_job_resume(job);
289
- job_user_resume(job, errp);
290
+ job_user_resume_locked(job, errp);
291
aio_context_release(aio_context);
292
}
293
294
void qmp_job_complete(const char *id, Error **errp)
295
{
296
AioContext *aio_context;
297
- Job *job = find_job(id, &aio_context, errp);
298
+ Job *job;
299
+
300
+ JOB_LOCK_GUARD();
301
+ job = find_job_locked(id, &aio_context, errp);
302
303
if (!job) {
304
return;
305
}
306
307
trace_qmp_job_complete(job);
308
- job_complete(job, errp);
309
+ job_complete_locked(job, errp);
310
aio_context_release(aio_context);
311
}
312
313
void qmp_job_finalize(const char *id, Error **errp)
314
{
315
AioContext *aio_context;
316
- Job *job = find_job(id, &aio_context, errp);
317
+ Job *job;
318
+
319
+ JOB_LOCK_GUARD();
320
+ job = find_job_locked(id, &aio_context, errp);
321
322
if (!job) {
323
return;
324
}
325
326
trace_qmp_job_finalize(job);
327
- job_ref(job);
328
- job_finalize(job, errp);
329
+ job_ref_locked(job);
330
+ job_finalize_locked(job, errp);
331
332
/*
333
* Job's context might have changed via job_finalize (and job_txn_apply
334
@@ -XXX,XX +XXX,XX @@ void qmp_job_finalize(const char *id, Error **errp)
335
* one.
336
*/
337
aio_context = job->aio_context;
338
- job_unref(job);
339
+ job_unref_locked(job);
340
aio_context_release(aio_context);
341
}
342
343
void qmp_job_dismiss(const char *id, Error **errp)
344
{
345
AioContext *aio_context;
346
- Job *job = find_job(id, &aio_context, errp);
347
+ Job *job;
348
+
349
+ JOB_LOCK_GUARD();
350
+ job = find_job_locked(id, &aio_context, errp);
351
352
if (!job) {
353
return;
354
}
355
356
trace_qmp_job_dismiss(job);
357
- job_dismiss(&job, errp);
358
+ job_dismiss_locked(&job, errp);
359
aio_context_release(aio_context);
360
}
361
83
--
362
--
84
1.8.3.1
363
2.37.3
85
86
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Specification: "FAT: General overview of on-disk format" v1.03, page 23
3
Add missing job synchronization in the unit tests, with
4
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
4
explicit locks.
5
6
We are deliberately using _locked functions wrapped by a guard
7
instead of a normal call because the normal call will be removed
8
in future, as the only usage is limited to the tests.
9
10
In other words, if a function like job_pause() is/will be only used
11
in tests to avoid:
12
13
WITH_JOB_LOCK_GUARD(){
14
job_pause_locked();
15
}
16
17
then it is not worth keeping job_pause(), and just use the guard.
18
19
Note: at this stage, job_{lock/unlock} and job lock guard macros
20
are *nop*.
21
22
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
23
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
Message-Id: <20220926093214.506243-10-eesposit@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
27
---
7
block/vvfat.c | 9 +++++++--
28
tests/unit/test-bdrv-drain.c | 76 ++++++++++++--------
8
1 file changed, 7 insertions(+), 2 deletions(-)
29
tests/unit/test-block-iothread.c | 8 ++-
9
30
tests/unit/test-blockjob-txn.c | 24 ++++---
10
diff --git a/block/vvfat.c b/block/vvfat.c
31
tests/unit/test-blockjob.c | 115 +++++++++++++++++++------------
32
4 files changed, 140 insertions(+), 83 deletions(-)
33
34
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
11
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
12
--- a/block/vvfat.c
36
--- a/tests/unit/test-bdrv-drain.c
13
+++ b/block/vvfat.c
37
+++ b/tests/unit/test-bdrv-drain.c
14
@@ -XXX,XX +XXX,XX @@ static direntry_t *create_short_filename(BDRVVVFATState *s,
38
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
15
}
39
}
16
}
40
}
17
41
18
+ if (entry->name[0] == 0xe5) {
42
- g_assert_cmpint(job->job.pause_count, ==, 0);
19
+ entry->name[0] = 0x05;
43
- g_assert_false(job->job.paused);
44
- g_assert_true(tjob->running);
45
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
46
+ WITH_JOB_LOCK_GUARD() {
47
+ g_assert_cmpint(job->job.pause_count, ==, 0);
48
+ g_assert_false(job->job.paused);
49
+ g_assert_true(tjob->running);
50
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
51
+ }
52
53
do_drain_begin_unlocked(drain_type, drain_bs);
54
55
- if (drain_type == BDRV_DRAIN_ALL) {
56
- /* bdrv_drain_all() drains both src and target */
57
- g_assert_cmpint(job->job.pause_count, ==, 2);
58
- } else {
59
- g_assert_cmpint(job->job.pause_count, ==, 1);
60
+ WITH_JOB_LOCK_GUARD() {
61
+ if (drain_type == BDRV_DRAIN_ALL) {
62
+ /* bdrv_drain_all() drains both src and target */
63
+ g_assert_cmpint(job->job.pause_count, ==, 2);
64
+ } else {
65
+ g_assert_cmpint(job->job.pause_count, ==, 1);
66
+ }
67
+ g_assert_true(job->job.paused);
68
+ g_assert_false(job->job.busy); /* The job is paused */
69
}
70
- g_assert_true(job->job.paused);
71
- g_assert_false(job->job.busy); /* The job is paused */
72
73
do_drain_end_unlocked(drain_type, drain_bs);
74
75
if (use_iothread) {
76
- /* paused is reset in the I/O thread, wait for it */
77
+ /*
78
+ * Here we are waiting for the paused status to change,
79
+ * so don't bother protecting the read every time.
80
+ *
81
+ * paused is reset in the I/O thread, wait for it
82
+ */
83
while (job->job.paused) {
84
aio_poll(qemu_get_aio_context(), false);
85
}
86
}
87
88
- g_assert_cmpint(job->job.pause_count, ==, 0);
89
- g_assert_false(job->job.paused);
90
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
91
+ WITH_JOB_LOCK_GUARD() {
92
+ g_assert_cmpint(job->job.pause_count, ==, 0);
93
+ g_assert_false(job->job.paused);
94
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
95
+ }
96
97
do_drain_begin_unlocked(drain_type, target);
98
99
- if (drain_type == BDRV_DRAIN_ALL) {
100
- /* bdrv_drain_all() drains both src and target */
101
- g_assert_cmpint(job->job.pause_count, ==, 2);
102
- } else {
103
- g_assert_cmpint(job->job.pause_count, ==, 1);
104
+ WITH_JOB_LOCK_GUARD() {
105
+ if (drain_type == BDRV_DRAIN_ALL) {
106
+ /* bdrv_drain_all() drains both src and target */
107
+ g_assert_cmpint(job->job.pause_count, ==, 2);
108
+ } else {
109
+ g_assert_cmpint(job->job.pause_count, ==, 1);
110
+ }
111
+ g_assert_true(job->job.paused);
112
+ g_assert_false(job->job.busy); /* The job is paused */
113
}
114
- g_assert_true(job->job.paused);
115
- g_assert_false(job->job.busy); /* The job is paused */
116
117
do_drain_end_unlocked(drain_type, target);
118
119
if (use_iothread) {
120
- /* paused is reset in the I/O thread, wait for it */
121
+ /*
122
+ * Here we are waiting for the paused status to change,
123
+ * so don't bother protecting the read every time.
124
+ *
125
+ * paused is reset in the I/O thread, wait for it
126
+ */
127
while (job->job.paused) {
128
aio_poll(qemu_get_aio_context(), false);
129
}
130
}
131
132
- g_assert_cmpint(job->job.pause_count, ==, 0);
133
- g_assert_false(job->job.paused);
134
- g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
135
+ WITH_JOB_LOCK_GUARD() {
136
+ g_assert_cmpint(job->job.pause_count, ==, 0);
137
+ g_assert_false(job->job.paused);
138
+ g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
139
+ }
140
141
aio_context_acquire(ctx);
142
- ret = job_complete_sync(&job->job, &error_abort);
143
+ WITH_JOB_LOCK_GUARD() {
144
+ ret = job_complete_sync_locked(&job->job, &error_abort);
145
+ }
146
g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO));
147
148
if (use_iothread) {
149
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/tests/unit/test-block-iothread.c
152
+++ b/tests/unit/test-block-iothread.c
153
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
154
}
155
156
aio_context_acquire(ctx);
157
- job_complete_sync(&tjob->common.job, &error_abort);
158
+ WITH_JOB_LOCK_GUARD() {
159
+ job_complete_sync_locked(&tjob->common.job, &error_abort);
160
+ }
161
blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
162
aio_context_release(ctx);
163
164
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
165
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
166
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
167
&error_abort);
168
- job = job_get("job0");
169
+ WITH_JOB_LOCK_GUARD() {
170
+ job = job_get_locked("job0");
171
+ }
172
filter = bdrv_find_node("filter_node");
173
174
/* Change the AioContext of src */
175
diff --git a/tests/unit/test-blockjob-txn.c b/tests/unit/test-blockjob-txn.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/tests/unit/test-blockjob-txn.c
178
+++ b/tests/unit/test-blockjob-txn.c
179
@@ -XXX,XX +XXX,XX @@ static void test_single_job(int expected)
180
job = test_block_job_start(1, true, expected, &result, txn);
181
job_start(&job->job);
182
183
- if (expected == -ECANCELED) {
184
- job_cancel(&job->job, false);
185
+ WITH_JOB_LOCK_GUARD() {
186
+ if (expected == -ECANCELED) {
187
+ job_cancel_locked(&job->job, false);
188
+ }
189
}
190
191
while (result == -EINPROGRESS) {
192
@@ -XXX,XX +XXX,XX @@ static void test_pair_jobs(int expected1, int expected2)
193
/* Release our reference now to trigger as many nice
194
* use-after-free bugs as possible.
195
*/
196
- job_txn_unref(txn);
197
+ WITH_JOB_LOCK_GUARD() {
198
+ job_txn_unref_locked(txn);
199
200
- if (expected1 == -ECANCELED) {
201
- job_cancel(&job1->job, false);
202
- }
203
- if (expected2 == -ECANCELED) {
204
- job_cancel(&job2->job, false);
205
+ if (expected1 == -ECANCELED) {
206
+ job_cancel_locked(&job1->job, false);
207
+ }
208
+ if (expected2 == -ECANCELED) {
209
+ job_cancel_locked(&job2->job, false);
210
+ }
211
}
212
213
while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
214
@@ -XXX,XX +XXX,XX @@ static void test_pair_jobs_fail_cancel_race(void)
215
job_start(&job1->job);
216
job_start(&job2->job);
217
218
- job_cancel(&job1->job, false);
219
+ WITH_JOB_LOCK_GUARD() {
220
+ job_cancel_locked(&job1->job, false);
221
+ }
222
223
/* Now make job2 finish before the main loop kicks jobs. This simulates
224
* the race between a pending kick and another job completing.
225
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/unit/test-blockjob.c
228
+++ b/tests/unit/test-blockjob.c
229
@@ -XXX,XX +XXX,XX @@ static CancelJob *create_common(Job **pjob)
230
bjob = mk_job(blk, "Steve", &test_cancel_driver, true,
231
JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS);
232
job = &bjob->job;
233
- job_ref(job);
234
- assert(job->status == JOB_STATUS_CREATED);
235
+ WITH_JOB_LOCK_GUARD() {
236
+ job_ref_locked(job);
237
+ assert(job->status == JOB_STATUS_CREATED);
20
+ }
238
+ }
21
+
239
+
22
/* numeric-tail generation */
240
s = container_of(bjob, CancelJob, common);
23
for (j = 0; j < 8; j++) {
241
s->blk = blk;
24
if (entry->name[j] == ' ') {
242
25
@@ -XXX,XX +XXX,XX @@ static inline void init_fat(BDRVVVFATState* s)
243
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
26
244
aio_context_acquire(ctx);
27
}
245
28
246
job_cancel_sync(&job->job, true);
29
-/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! */
247
- if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) {
30
-/* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */
248
- Job *dummy = &job->job;
31
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
249
- job_dismiss(&dummy, &error_abort);
32
unsigned int directory_start, const char* filename, int is_dot)
250
+ WITH_JOB_LOCK_GUARD() {
251
+ if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) {
252
+ Job *dummy = &job->job;
253
+ job_dismiss_locked(&dummy, &error_abort);
254
+ }
255
+ assert(job->job.status == JOB_STATUS_NULL);
256
+ job_unref_locked(&job->job);
257
}
258
- assert(job->job.status == JOB_STATUS_NULL);
259
- job_unref(&job->job);
260
destroy_blk(blk);
261
262
aio_context_release(ctx);
263
@@ -XXX,XX +XXX,XX @@ static void test_cancel_created(void)
264
cancel_common(s);
265
}
266
267
+static void assert_job_status_is(Job *job, int status)
268
+{
269
+ WITH_JOB_LOCK_GUARD() {
270
+ assert(job->status == status);
271
+ }
272
+}
273
+
274
static void test_cancel_running(void)
33
{
275
{
34
@@ -XXX,XX +XXX,XX @@ static int parse_short_name(BDRVVVFATState* s,
276
Job *job;
35
} else
277
@@ -XXX,XX +XXX,XX @@ static void test_cancel_running(void)
36
lfn->name[i + j + 1] = '\0';
278
s = create_common(&job);
37
279
38
+ if (lfn->name[0] == 0x05) {
280
job_start(job);
39
+ lfn->name[0] = 0xe5;
281
- assert(job->status == JOB_STATUS_RUNNING);
40
+ }
282
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
41
lfn->len = strlen((char*)lfn->name);
283
42
284
cancel_common(s);
43
return 0;
285
}
286
@@ -XXX,XX +XXX,XX @@ static void test_cancel_paused(void)
287
s = create_common(&job);
288
289
job_start(job);
290
- assert(job->status == JOB_STATUS_RUNNING);
291
-
292
- job_user_pause(job, &error_abort);
293
+ WITH_JOB_LOCK_GUARD() {
294
+ assert(job->status == JOB_STATUS_RUNNING);
295
+ job_user_pause_locked(job, &error_abort);
296
+ }
297
job_enter(job);
298
- assert(job->status == JOB_STATUS_PAUSED);
299
+ assert_job_status_is(job, JOB_STATUS_PAUSED);
300
301
cancel_common(s);
302
}
303
@@ -XXX,XX +XXX,XX @@ static void test_cancel_ready(void)
304
s = create_common(&job);
305
306
job_start(job);
307
- assert(job->status == JOB_STATUS_RUNNING);
308
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
309
310
s->should_converge = true;
311
job_enter(job);
312
- assert(job->status == JOB_STATUS_READY);
313
+ assert_job_status_is(job, JOB_STATUS_READY);
314
315
cancel_common(s);
316
}
317
@@ -XXX,XX +XXX,XX @@ static void test_cancel_standby(void)
318
s = create_common(&job);
319
320
job_start(job);
321
- assert(job->status == JOB_STATUS_RUNNING);
322
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
323
324
s->should_converge = true;
325
job_enter(job);
326
- assert(job->status == JOB_STATUS_READY);
327
-
328
- job_user_pause(job, &error_abort);
329
+ WITH_JOB_LOCK_GUARD() {
330
+ assert(job->status == JOB_STATUS_READY);
331
+ job_user_pause_locked(job, &error_abort);
332
+ }
333
job_enter(job);
334
- assert(job->status == JOB_STATUS_STANDBY);
335
+ assert_job_status_is(job, JOB_STATUS_STANDBY);
336
337
cancel_common(s);
338
}
339
@@ -XXX,XX +XXX,XX @@ static void test_cancel_pending(void)
340
s = create_common(&job);
341
342
job_start(job);
343
- assert(job->status == JOB_STATUS_RUNNING);
344
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
345
346
s->should_converge = true;
347
job_enter(job);
348
- assert(job->status == JOB_STATUS_READY);
349
-
350
- job_complete(job, &error_abort);
351
+ WITH_JOB_LOCK_GUARD() {
352
+ assert(job->status == JOB_STATUS_READY);
353
+ job_complete_locked(job, &error_abort);
354
+ }
355
job_enter(job);
356
while (!job->deferred_to_main_loop) {
357
aio_poll(qemu_get_aio_context(), true);
358
}
359
- assert(job->status == JOB_STATUS_READY);
360
+ assert_job_status_is(job, JOB_STATUS_READY);
361
aio_poll(qemu_get_aio_context(), true);
362
- assert(job->status == JOB_STATUS_PENDING);
363
+ assert_job_status_is(job, JOB_STATUS_PENDING);
364
365
cancel_common(s);
366
}
367
@@ -XXX,XX +XXX,XX @@ static void test_cancel_concluded(void)
368
s = create_common(&job);
369
370
job_start(job);
371
- assert(job->status == JOB_STATUS_RUNNING);
372
+ assert_job_status_is(job, JOB_STATUS_RUNNING);
373
374
s->should_converge = true;
375
job_enter(job);
376
- assert(job->status == JOB_STATUS_READY);
377
-
378
- job_complete(job, &error_abort);
379
+ WITH_JOB_LOCK_GUARD() {
380
+ assert(job->status == JOB_STATUS_READY);
381
+ job_complete_locked(job, &error_abort);
382
+ }
383
job_enter(job);
384
while (!job->deferred_to_main_loop) {
385
aio_poll(qemu_get_aio_context(), true);
386
}
387
- assert(job->status == JOB_STATUS_READY);
388
+ assert_job_status_is(job, JOB_STATUS_READY);
389
aio_poll(qemu_get_aio_context(), true);
390
- assert(job->status == JOB_STATUS_PENDING);
391
+ assert_job_status_is(job, JOB_STATUS_PENDING);
392
393
aio_context_acquire(job->aio_context);
394
- job_finalize(job, &error_abort);
395
+ WITH_JOB_LOCK_GUARD() {
396
+ job_finalize_locked(job, &error_abort);
397
+ }
398
aio_context_release(job->aio_context);
399
- assert(job->status == JOB_STATUS_CONCLUDED);
400
+ assert_job_status_is(job, JOB_STATUS_CONCLUDED);
401
402
cancel_common(s);
403
}
404
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
405
bjob = mk_job(blk, "job", &test_yielding_driver, true,
406
JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS);
407
job = &bjob->job;
408
- assert(job->status == JOB_STATUS_CREATED);
409
+ assert_job_status_is(job, JOB_STATUS_CREATED);
410
411
/* Wait for the job to become READY */
412
job_start(job);
413
aio_context_acquire(ctx);
414
+ /*
415
+ * Here we are waiting for the status to change, so don't bother
416
+ * protecting the read every time.
417
+ */
418
AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY);
419
aio_context_release(ctx);
420
421
/* Begin the drained section, pausing the job */
422
bdrv_drain_all_begin();
423
- assert(job->status == JOB_STATUS_STANDBY);
424
+ assert_job_status_is(job, JOB_STATUS_STANDBY);
425
+
426
/* Lock the IO thread to prevent the job from being run */
427
aio_context_acquire(ctx);
428
/* This will schedule the job to resume it */
429
bdrv_drain_all_end();
430
431
- /* But the job cannot run, so it will remain on standby */
432
- assert(job->status == JOB_STATUS_STANDBY);
433
+ WITH_JOB_LOCK_GUARD() {
434
+ /* But the job cannot run, so it will remain on standby */
435
+ assert(job->status == JOB_STATUS_STANDBY);
436
437
- /* Even though the job is on standby, this should work */
438
- job_complete(job, &error_abort);
439
+ /* Even though the job is on standby, this should work */
440
+ job_complete_locked(job, &error_abort);
441
442
- /* The test is done now, clean up. */
443
- job_finish_sync(job, NULL, &error_abort);
444
- assert(job->status == JOB_STATUS_PENDING);
445
+ /* The test is done now, clean up. */
446
+ job_finish_sync_locked(job, NULL, &error_abort);
447
+ assert(job->status == JOB_STATUS_PENDING);
448
449
- job_finalize(job, &error_abort);
450
- assert(job->status == JOB_STATUS_CONCLUDED);
451
+ job_finalize_locked(job, &error_abort);
452
+ assert(job->status == JOB_STATUS_CONCLUDED);
453
454
- job_dismiss(&job, &error_abort);
455
+ job_dismiss_locked(&job, &error_abort);
456
+ }
457
458
destroy_blk(blk);
459
aio_context_release(ctx);
44
--
460
--
45
1.8.3.1
461
2.37.3
46
47
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
Once job lock is used and aiocontext is removed, mirror has
4
easier to reason about than sector-based. Convert another internal
4
to perform job operations under the same critical section,
5
function (no semantic change), and add mirror_clip_bytes() as a
5
Note: at this stage, job_{lock/unlock} and job lock guard macros
6
counterpart to mirror_clip_sectors(). Some of the conversion is
6
are *nop*.
7
a bit tricky, requiring temporaries to convert between units; it
8
will be cleared up in a following patch.
9
7
10
Signed-off-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Reviewed-by: Jeff Cody <jcody@redhat.com>
10
Message-Id: <20220926093214.506243-11-eesposit@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
block/mirror.c | 63 ++++++++++++++++++++++++++++++++++------------------------
14
block/mirror.c | 13 +++++++++----
17
1 file changed, 37 insertions(+), 26 deletions(-)
15
1 file changed, 9 insertions(+), 4 deletions(-)
18
16
19
diff --git a/block/mirror.c b/block/mirror.c
17
diff --git a/block/mirror.c b/block/mirror.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/block/mirror.c
19
--- a/block/mirror.c
22
+++ b/block/mirror.c
20
+++ b/block/mirror.c
23
@@ -XXX,XX +XXX,XX @@ static void mirror_read_complete(void *opaque, int ret)
21
@@ -XXX,XX +XXX,XX @@ static void mirror_complete(Job *job, Error **errp)
24
aio_context_release(blk_get_aio_context(s->common.blk));
22
s->should_complete = true;
23
24
/* If the job is paused, it will be re-entered when it is resumed */
25
- if (!job->paused) {
26
- job_enter(job);
27
+ WITH_JOB_LOCK_GUARD() {
28
+ if (!job->paused) {
29
+ job_enter_cond_locked(job, NULL);
30
+ }
31
}
25
}
32
}
26
33
27
+/* Clip bytes relative to offset to not exceed end-of-file */
34
@@ -XXX,XX +XXX,XX @@ static bool mirror_drained_poll(BlockJob *job)
28
+static inline int64_t mirror_clip_bytes(MirrorBlockJob *s,
35
* from one of our own drain sections, to avoid a deadlock waiting for
29
+ int64_t offset,
36
* ourselves.
30
+ int64_t bytes)
37
*/
31
+{
38
- if (!s->common.job.paused && !job_is_cancelled(&job->job) && !s->in_drain) {
32
+ return MIN(bytes, s->bdev_length - offset);
39
- return true;
33
+}
40
+ WITH_JOB_LOCK_GUARD() {
34
+
41
+ if (!s->common.job.paused && !job_is_cancelled_locked(&job->job)
35
+/* Clip nb_sectors relative to sector_num to not exceed end-of-file */
42
+ && !s->in_drain) {
36
static inline int mirror_clip_sectors(MirrorBlockJob *s,
43
+ return true;
37
int64_t sector_num,
44
+ }
38
int nb_sectors)
39
@@ -XXX,XX +XXX,XX @@ static inline int mirror_clip_sectors(MirrorBlockJob *s,
40
s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
41
}
42
43
-/* Round sector_num and/or nb_sectors to target cluster if COW is needed, and
44
- * return the offset of the adjusted tail sector against original. */
45
-static int mirror_cow_align(MirrorBlockJob *s,
46
- int64_t *sector_num,
47
- int *nb_sectors)
48
+/* Round offset and/or bytes to target cluster if COW is needed, and
49
+ * return the offset of the adjusted tail against original. */
50
+static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
51
+ unsigned int *bytes)
52
{
53
bool need_cow;
54
int ret = 0;
55
- int chunk_sectors = s->granularity >> BDRV_SECTOR_BITS;
56
- int64_t align_sector_num = *sector_num;
57
- int align_nb_sectors = *nb_sectors;
58
- int max_sectors = chunk_sectors * s->max_iov;
59
+ int64_t align_offset = *offset;
60
+ unsigned int align_bytes = *bytes;
61
+ int max_bytes = s->granularity * s->max_iov;
62
63
- need_cow = !test_bit(*sector_num / chunk_sectors, s->cow_bitmap);
64
- need_cow |= !test_bit((*sector_num + *nb_sectors - 1) / chunk_sectors,
65
+ need_cow = !test_bit(*offset / s->granularity, s->cow_bitmap);
66
+ need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity,
67
s->cow_bitmap);
68
if (need_cow) {
69
- bdrv_round_sectors_to_clusters(blk_bs(s->target), *sector_num,
70
- *nb_sectors, &align_sector_num,
71
- &align_nb_sectors);
72
+ bdrv_round_to_clusters(blk_bs(s->target), *offset, *bytes,
73
+ &align_offset, &align_bytes);
74
}
45
}
75
46
76
- if (align_nb_sectors > max_sectors) {
47
return !!s->in_flight;
77
- align_nb_sectors = max_sectors;
78
+ if (align_bytes > max_bytes) {
79
+ align_bytes = max_bytes;
80
if (need_cow) {
81
- align_nb_sectors = QEMU_ALIGN_DOWN(align_nb_sectors,
82
- s->target_cluster_size >>
83
- BDRV_SECTOR_BITS);
84
+ align_bytes = QEMU_ALIGN_DOWN(align_bytes, s->target_cluster_size);
85
}
86
}
87
- /* Clipping may result in align_nb_sectors unaligned to chunk boundary, but
88
+ /* Clipping may result in align_bytes unaligned to chunk boundary, but
89
* that doesn't matter because it's already the end of source image. */
90
- align_nb_sectors = mirror_clip_sectors(s, align_sector_num,
91
- align_nb_sectors);
92
+ align_bytes = mirror_clip_bytes(s, align_offset, align_bytes);
93
94
- ret = align_sector_num + align_nb_sectors - (*sector_num + *nb_sectors);
95
- *sector_num = align_sector_num;
96
- *nb_sectors = align_nb_sectors;
97
+ ret = align_offset + align_bytes - (*offset + *bytes);
98
+ *offset = align_offset;
99
+ *bytes = align_bytes;
100
assert(ret >= 0);
101
return ret;
102
}
103
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
104
nb_sectors = MIN(s->buf_size >> BDRV_SECTOR_BITS, nb_sectors);
105
nb_sectors = MIN(max_sectors, nb_sectors);
106
assert(nb_sectors);
107
+ assert(nb_sectors < BDRV_REQUEST_MAX_SECTORS);
108
ret = nb_sectors;
109
110
if (s->cow_bitmap) {
111
- ret += mirror_cow_align(s, &sector_num, &nb_sectors);
112
+ int64_t offset = sector_num * BDRV_SECTOR_SIZE;
113
+ unsigned int bytes = nb_sectors * BDRV_SECTOR_SIZE;
114
+ int gap;
115
+
116
+ gap = mirror_cow_align(s, &offset, &bytes);
117
+ sector_num = offset / BDRV_SECTOR_SIZE;
118
+ nb_sectors = bytes / BDRV_SECTOR_SIZE;
119
+ ret += gap / BDRV_SECTOR_SIZE;
120
}
121
assert(nb_sectors << BDRV_SECTOR_BITS <= s->buf_size);
122
/* The sector range must meet granularity because:
123
--
48
--
124
1.8.3.1
49
2.37.3
125
126
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Now that all encryption keys must be provided upfront via
3
Now that the API offers also _locked() functions, take advantage
4
the QCryptoSecret API and associated block driver properties
4
of it and give also the caller control to take the lock and call
5
there is no need for any explicit encryption handling APIs
5
_locked functions.
6
in the block layer. Encryption can be handled transparently
6
7
within the block driver. We only retain an API for querying
7
This makes sense especially when we have for loops, because it
8
whether an image is encrypted or not, since that is a
8
makes no sense to have:
9
potentially useful piece of metadata to report to the user.
9
10
10
for(job = job_next(); ...)
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
where each job_next() takes the lock internally.
13
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
13
Instead we want
14
Message-id: 20170623162419.26068-18-berrange@redhat.com
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
JOB_LOCK_GUARD();
16
for(job = job_next_locked(); ...)
17
18
In addition, protect also direct field accesses, by either creating a
19
new critical section or widening the existing ones.
20
21
Note: at this stage, job_{lock/unlock} and job lock guard macros
22
are *nop*.
23
24
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
25
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
26
Message-Id: <20220926093214.506243-12-eesposit@redhat.com>
27
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
29
---
17
block.c | 77 +----------------------------------------------
30
block.c | 17 ++++++++++-------
18
block/crypto.c | 1 -
31
blockdev.c | 14 ++++++++++----
19
block/qapi.c | 2 +-
32
blockjob.c | 35 ++++++++++++++++++++++-------------
20
block/qcow.c | 8 ++++-
33
job-qmp.c | 9 ++++++---
21
block/qcow2.c | 1 -
34
monitor/qmp-cmds.c | 7 +++++--
22
blockdev.c | 37 ++---------------------
35
qemu-img.c | 15 ++++++++++-----
23
hmp-commands.hx | 2 ++
36
6 files changed, 63 insertions(+), 34 deletions(-)
24
include/block/block.h | 3 --
25
include/block/block_int.h | 1 -
26
include/qapi/error.h | 1 -
27
qapi/block-core.json | 37 ++---------------------
28
qapi/common.json | 5 +--
29
12 files changed, 16 insertions(+), 159 deletions(-)
30
37
31
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
40
--- a/block.c
34
+++ b/block.c
41
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
36
goto close_and_fail;
37
}
38
39
- if (!bdrv_key_required(bs)) {
40
- bdrv_parent_cb_change_media(bs, true);
41
- } else if (!runstate_check(RUN_STATE_PRELAUNCH)
42
- && !runstate_check(RUN_STATE_INMIGRATE)
43
- && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
44
- error_setg(errp,
45
- "Guest must be stopped for opening of encrypted image");
46
- goto close_and_fail;
47
- }
48
+ bdrv_parent_cb_change_media(bs, true);
49
50
QDECREF(options);
51
52
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
42
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
53
bs->backing_format[0] = '\0';
43
54
bs->total_sectors = 0;
44
void bdrv_close_all(void)
55
bs->encrypted = false;
56
- bs->valid_key = false;
57
bs->sg = false;
58
QDECREF(bs->options);
59
QDECREF(bs->explicit_options);
60
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_encrypted(BlockDriverState *bs)
61
return bs->encrypted;
62
}
63
64
-bool bdrv_key_required(BlockDriverState *bs)
65
-{
66
- BdrvChild *backing = bs->backing;
67
-
68
- if (backing && backing->bs->encrypted && !backing->bs->valid_key) {
69
- return true;
70
- }
71
- return (bs->encrypted && !bs->valid_key);
72
-}
73
-
74
-int bdrv_set_key(BlockDriverState *bs, const char *key)
75
-{
76
- int ret;
77
- if (bs->backing && bs->backing->bs->encrypted) {
78
- ret = bdrv_set_key(bs->backing->bs, key);
79
- if (ret < 0)
80
- return ret;
81
- if (!bs->encrypted)
82
- return 0;
83
- }
84
- if (!bs->encrypted) {
85
- return -EINVAL;
86
- } else if (!bs->drv || !bs->drv->bdrv_set_key) {
87
- return -ENOMEDIUM;
88
- }
89
- ret = bs->drv->bdrv_set_key(bs, key);
90
- if (ret < 0) {
91
- bs->valid_key = false;
92
- } else if (!bs->valid_key) {
93
- /* call the change callback now, we skipped it on open */
94
- bs->valid_key = true;
95
- bdrv_parent_cb_change_media(bs, true);
96
- }
97
- return ret;
98
-}
99
-
100
-/*
101
- * Provide an encryption key for @bs.
102
- * If @key is non-null:
103
- * If @bs is not encrypted, fail.
104
- * Else if the key is invalid, fail.
105
- * Else set @bs's key to @key, replacing the existing key, if any.
106
- * If @key is null:
107
- * If @bs is encrypted and still lacks a key, fail.
108
- * Else do nothing.
109
- * On failure, store an error object through @errp if non-null.
110
- */
111
-void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp)
112
-{
113
- if (key) {
114
- if (!bdrv_is_encrypted(bs)) {
115
- error_setg(errp, "Node '%s' is not encrypted",
116
- bdrv_get_device_or_node_name(bs));
117
- } else if (bdrv_set_key(bs, key) < 0) {
118
- error_setg(errp, QERR_INVALID_PASSWORD);
119
- }
120
- } else {
121
- if (bdrv_key_required(bs)) {
122
- error_set(errp, ERROR_CLASS_DEVICE_ENCRYPTED,
123
- "'%s' (%s) is encrypted",
124
- bdrv_get_device_or_node_name(bs),
125
- bdrv_get_encrypted_filename(bs));
126
- }
127
- }
128
-}
129
-
130
const char *bdrv_get_format_name(BlockDriverState *bs)
131
{
45
{
132
return bs->drv ? bs->drv->format_name : NULL;
46
- assert(job_next(NULL) == NULL);
133
diff --git a/block/crypto.c b/block/crypto.c
47
GLOBAL_STATE_CODE();
134
index XXXXXXX..XXXXXXX 100644
48
+ assert(job_next(NULL) == NULL);
135
--- a/block/crypto.c
49
136
+++ b/block/crypto.c
50
/* Drop references from requests still in flight, such as canceled block
137
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
51
* jobs whose AIO context has not been polled yet */
138
}
52
@@ -XXX,XX +XXX,XX @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp)
139
53
}
140
bs->encrypted = true;
54
}
141
- bs->valid_key = true;
55
142
56
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
143
ret = 0;
57
- GSList *el;
144
cleanup:
58
+ WITH_JOB_LOCK_GUARD() {
145
diff --git a/block/qapi.c b/block/qapi.c
59
+ for (job = block_job_next_locked(NULL); job;
146
index XXXXXXX..XXXXXXX 100644
60
+ job = block_job_next_locked(job)) {
147
--- a/block/qapi.c
61
+ GSList *el;
148
+++ b/block/qapi.c
62
149
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
63
- xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
150
info->ro = bs->read_only;
64
- job->job.id);
151
info->drv = g_strdup(bs->drv->format_name);
65
- for (el = job->nodes; el; el = el->next) {
152
info->encrypted = bs->encrypted;
66
- xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
153
- info->encryption_key_missing = bdrv_key_required(bs);
67
+ xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB,
154
+ info->encryption_key_missing = false;
68
+ job->job.id);
155
69
+ for (el = job->nodes; el; el = el->next) {
156
info->cache = g_new(BlockdevCacheInfo, 1);
70
+ xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data);
157
*info->cache = (BlockdevCacheInfo) {
71
+ }
158
diff --git a/block/qcow.c b/block/qcow.c
72
}
159
index XXXXXXX..XXXXXXX 100644
73
}
160
--- a/block/qcow.c
74
161
+++ b/block/qcow.c
162
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
163
goto fail;
164
}
165
bs->encrypted = true;
166
- bs->valid_key = true;
167
+ } else {
168
+ if (encryptfmt) {
169
+ error_setg(errp, "No encryption in image header, but options "
170
+ "specified format '%s'", encryptfmt);
171
+ ret = -EINVAL;
172
+ goto fail;
173
+ }
174
}
175
s->cluster_bits = header.cluster_bits;
176
s->cluster_size = 1 << s->cluster_bits;
177
diff --git a/block/qcow2.c b/block/qcow2.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/block/qcow2.c
180
+++ b/block/qcow2.c
181
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
182
}
183
184
bs->encrypted = true;
185
- bs->valid_key = true;
186
}
187
188
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
189
diff --git a/blockdev.c b/blockdev.c
75
diff --git a/blockdev.c b/blockdev.c
190
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
191
--- a/blockdev.c
77
--- a/blockdev.c
192
+++ b/blockdev.c
78
+++ b/blockdev.c
193
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
79
@@ -XXX,XX +XXX,XX @@ void blockdev_mark_auto_del(BlockBackend *blk)
194
80
return;
195
bs->detect_zeroes = detect_zeroes;
81
}
196
82
197
- if (bdrv_key_required(bs)) {
83
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
198
- autostart = 0;
84
+ JOB_LOCK_GUARD();
199
- }
85
+
200
-
86
+ for (job = block_job_next_locked(NULL); job;
201
block_acct_setup(blk_get_stats(blk), account_invalid, account_failed);
87
+ job = block_job_next_locked(job)) {
202
88
if (block_job_has_bdrv(job, blk_bs(blk))) {
203
if (!parse_stats_intervals(blk_get_stats(blk), interval_list, errp)) {
89
AioContext *aio_context = job->job.aio_context;
204
@@ -XXX,XX +XXX,XX @@ void qmp_block_passwd(bool has_device, const char *device,
90
aio_context_acquire(aio_context);
205
bool has_node_name, const char *node_name,
91
206
const char *password, Error **errp)
92
- job_cancel(&job->job, false);
93
+ job_cancel_locked(&job->job, false);
94
95
aio_context_release(aio_context);
96
}
97
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
98
BlockJobInfoList *head = NULL, **tail = &head;
99
BlockJob *job;
100
101
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
102
+ JOB_LOCK_GUARD();
103
+
104
+ for (job = block_job_next_locked(NULL); job;
105
+ job = block_job_next_locked(job)) {
106
BlockJobInfo *value;
107
AioContext *aio_context;
108
109
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
110
}
111
aio_context = block_job_get_aio_context(job);
112
aio_context_acquire(aio_context);
113
- value = block_job_query(job, errp);
114
+ value = block_job_query_locked(job, errp);
115
aio_context_release(aio_context);
116
if (!value) {
117
qapi_free_BlockJobInfoList(head);
118
diff --git a/blockjob.c b/blockjob.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/blockjob.c
121
+++ b/blockjob.c
122
@@ -XXX,XX +XXX,XX @@ static bool child_job_drained_poll(BdrvChild *c)
123
/* An inactive or completed job doesn't have any pending requests. Jobs
124
* with !job->busy are either already paused or have a pause point after
125
* being reentered, so no job driver code will run before they pause. */
126
- if (!job->busy || job_is_completed(job)) {
127
- return false;
128
+ WITH_JOB_LOCK_GUARD() {
129
+ if (!job->busy || job_is_completed_locked(job)) {
130
+ return false;
131
+ }
132
}
133
134
/* Otherwise, assume that it isn't fully stopped yet, but allow the job to
135
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
136
job->ready_notifier.notify = block_job_event_ready;
137
job->idle_notifier.notify = block_job_on_idle;
138
139
- notifier_list_add(&job->job.on_finalize_cancelled,
140
- &job->finalize_cancelled_notifier);
141
- notifier_list_add(&job->job.on_finalize_completed,
142
- &job->finalize_completed_notifier);
143
- notifier_list_add(&job->job.on_pending, &job->pending_notifier);
144
- notifier_list_add(&job->job.on_ready, &job->ready_notifier);
145
- notifier_list_add(&job->job.on_idle, &job->idle_notifier);
146
+ WITH_JOB_LOCK_GUARD() {
147
+ notifier_list_add(&job->job.on_finalize_cancelled,
148
+ &job->finalize_cancelled_notifier);
149
+ notifier_list_add(&job->job.on_finalize_completed,
150
+ &job->finalize_completed_notifier);
151
+ notifier_list_add(&job->job.on_pending, &job->pending_notifier);
152
+ notifier_list_add(&job->job.on_ready, &job->ready_notifier);
153
+ notifier_list_add(&job->job.on_idle, &job->idle_notifier);
154
+ }
155
156
error_setg(&job->blocker, "block device is in use by block job: %s",
157
job_type_str(&job->job));
158
@@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
159
action);
160
}
161
if (action == BLOCK_ERROR_ACTION_STOP) {
162
- if (!job->job.user_paused) {
163
- job_pause(&job->job);
164
- /* make the pause user visible, which will be resumed from QMP. */
165
- job->job.user_paused = true;
166
+ WITH_JOB_LOCK_GUARD() {
167
+ if (!job->job.user_paused) {
168
+ job_pause_locked(&job->job);
169
+ /*
170
+ * make the pause user visible, which will be
171
+ * resumed from QMP.
172
+ */
173
+ job->job.user_paused = true;
174
+ }
175
}
176
block_job_iostatus_set_err(job, error);
177
}
178
diff --git a/job-qmp.c b/job-qmp.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/job-qmp.c
181
+++ b/job-qmp.c
182
@@ -XXX,XX +XXX,XX @@ void qmp_job_dismiss(const char *id, Error **errp)
183
aio_context_release(aio_context);
184
}
185
186
-static JobInfo *job_query_single(Job *job, Error **errp)
187
+/* Called with job_mutex held. */
188
+static JobInfo *job_query_single_locked(Job *job, Error **errp)
207
{
189
{
208
- Error *local_err = NULL;
190
JobInfo *info;
209
- BlockDriverState *bs;
191
uint64_t progress_current;
210
- AioContext *aio_context;
192
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
211
-
193
JobInfoList *head = NULL, **tail = &head;
212
- bs = bdrv_lookup_bs(has_device ? device : NULL,
194
Job *job;
213
- has_node_name ? node_name : NULL,
195
214
- &local_err);
196
- for (job = job_next(NULL); job; job = job_next(job)) {
215
- if (local_err) {
197
+ JOB_LOCK_GUARD();
216
- error_propagate(errp, local_err);
217
- return;
218
- }
219
-
220
- aio_context = bdrv_get_aio_context(bs);
221
- aio_context_acquire(aio_context);
222
-
223
- bdrv_add_key(bs, password, errp);
224
-
225
- aio_context_release(aio_context);
226
+ error_setg(errp,
227
+ "Setting block passwords directly is no longer supported");
228
}
229
230
/*
231
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
232
goto fail;
233
}
234
235
- bdrv_add_key(medium_bs, NULL, &err);
236
- if (err) {
237
- error_propagate(errp, err);
238
- goto fail;
239
- }
240
-
241
rc = do_open_tray(has_device ? device : NULL,
242
has_id ? id : NULL,
243
false, &err);
244
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
245
246
QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list);
247
248
- if (bs && bdrv_key_required(bs)) {
249
- QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
250
- bdrv_unref(bs);
251
- error_setg(errp, "blockdev-add doesn't support encrypted devices");
252
- goto fail;
253
- }
254
-
255
fail:
256
visit_free(v);
257
}
258
diff --git a/hmp-commands.hx b/hmp-commands.hx
259
index XXXXXXX..XXXXXXX 100644
260
--- a/hmp-commands.hx
261
+++ b/hmp-commands.hx
262
@@ -XXX,XX +XXX,XX @@ STEXI
263
@item block_passwd @var{device} @var{password}
264
@findex block_passwd
265
Set the encrypted device @var{device} password to @var{password}
266
+
198
+
267
+This command is now obsolete and will always return an error since 2.10
199
+ for (job = job_next_locked(NULL); job; job = job_next_locked(job)) {
268
ETEXI
200
JobInfo *value;
269
201
AioContext *aio_context;
270
{
202
271
diff --git a/include/block/block.h b/include/block/block.h
203
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
272
index XXXXXXX..XXXXXXX 100644
204
}
273
--- a/include/block/block.h
205
aio_context = job->aio_context;
274
+++ b/include/block/block.h
206
aio_context_acquire(aio_context);
275
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_next(BdrvNextIterator *it);
207
- value = job_query_single(job, errp);
276
208
+ value = job_query_single_locked(job, errp);
277
BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
209
aio_context_release(aio_context);
278
bool bdrv_is_encrypted(BlockDriverState *bs);
210
if (!value) {
279
-bool bdrv_key_required(BlockDriverState *bs);
211
qapi_free_JobInfoList(head);
280
-int bdrv_set_key(BlockDriverState *bs, const char *key);
212
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
281
-void bdrv_add_key(BlockDriverState *bs, const char *key, Error **errp);
213
index XXXXXXX..XXXXXXX 100644
282
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
214
--- a/monitor/qmp-cmds.c
283
void *opaque);
215
+++ b/monitor/qmp-cmds.c
284
const char *bdrv_get_node_name(const BlockDriverState *bs);
216
@@ -XXX,XX +XXX,XX @@ void qmp_cont(Error **errp)
285
diff --git a/include/block/block_int.h b/include/block/block_int.h
217
blk_iostatus_reset(blk);
286
index XXXXXXX..XXXXXXX 100644
218
}
287
--- a/include/block/block_int.h
219
288
+++ b/include/block/block_int.h
220
- for (job = block_job_next(NULL); job; job = block_job_next(job)) {
289
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
221
- block_job_iostatus_reset(job);
290
int open_flags; /* flags used to open the file, re-used for re-open */
222
+ WITH_JOB_LOCK_GUARD() {
291
bool read_only; /* if true, the media is read only */
223
+ for (job = block_job_next_locked(NULL); job;
292
bool encrypted; /* if true, the media is encrypted */
224
+ job = block_job_next_locked(job)) {
293
- bool valid_key; /* if true, a valid encryption key has been set */
225
+ block_job_iostatus_reset_locked(job);
294
bool sg; /* if true, the device is a /dev/sg* */
226
+ }
295
bool probed; /* if true, format was probed rather than specified */
227
}
296
bool force_share; /* if true, always allow all shared permissions */
228
297
diff --git a/include/qapi/error.h b/include/qapi/error.h
229
/* Continuing after completed migration. Images have been inactivated to
298
index XXXXXXX..XXXXXXX 100644
230
diff --git a/qemu-img.c b/qemu-img.c
299
--- a/include/qapi/error.h
231
index XXXXXXX..XXXXXXX 100644
300
+++ b/include/qapi/error.h
232
--- a/qemu-img.c
301
@@ -XXX,XX +XXX,XX @@
233
+++ b/qemu-img.c
302
typedef enum ErrorClass {
234
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
303
ERROR_CLASS_GENERIC_ERROR = QAPI_ERROR_CLASS_GENERICERROR,
235
int ret = 0;
304
ERROR_CLASS_COMMAND_NOT_FOUND = QAPI_ERROR_CLASS_COMMANDNOTFOUND,
236
305
- ERROR_CLASS_DEVICE_ENCRYPTED = QAPI_ERROR_CLASS_DEVICEENCRYPTED,
237
aio_context_acquire(aio_context);
306
ERROR_CLASS_DEVICE_NOT_ACTIVE = QAPI_ERROR_CLASS_DEVICENOTACTIVE,
238
- job_ref(&job->job);
307
ERROR_CLASS_DEVICE_NOT_FOUND = QAPI_ERROR_CLASS_DEVICENOTFOUND,
239
+ job_lock();
308
ERROR_CLASS_KVM_MISSING_CAP = QAPI_ERROR_CLASS_KVMMISSINGCAP,
240
+ job_ref_locked(&job->job);
309
diff --git a/qapi/block-core.json b/qapi/block-core.json
241
do {
310
index XXXXXXX..XXXXXXX 100644
242
float progress = 0.0f;
311
--- a/qapi/block-core.json
243
+ job_unlock();
312
+++ b/qapi/block-core.json
244
aio_poll(aio_context, true);
313
@@ -XXX,XX +XXX,XX @@
245
314
#
246
progress_get_snapshot(&job->job.progress, &progress_current,
315
# @encrypted: true if the backing device is encrypted
247
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
316
#
248
progress = (float)progress_current / progress_total * 100.f;
317
-# @encryption_key_missing: true if the backing device is encrypted but an
249
}
318
-# valid encryption key is missing
250
qemu_progress_print(progress, 0);
319
+# @encryption_key_missing: Deprecated; always false
251
- } while (!job_is_ready(&job->job) && !job_is_completed(&job->job));
320
#
252
+ job_lock();
321
# @detect_zeroes: detect and optimize zero writes (Since 2.1)
253
+ } while (!job_is_ready_locked(&job->job) &&
322
#
254
+ !job_is_completed_locked(&job->job));
323
@@ -XXX,XX +XXX,XX @@
255
324
# This command sets the password of a block device that has not been open
256
- if (!job_is_completed(&job->job)) {
325
# with a password and requires one.
257
- ret = job_complete_sync(&job->job, errp);
326
#
258
+ if (!job_is_completed_locked(&job->job)) {
327
-# The two cases where this can happen are a block device is created through
259
+ ret = job_complete_sync_locked(&job->job, errp);
328
-# QEMU's initial command line or a block device is changed through the legacy
260
} else {
329
-# @change interface.
261
ret = job->job.ret;
330
-#
262
}
331
-# In the event that the block device is created through the initial command
263
- job_unref(&job->job);
332
-# line, the VM will start in the stopped state regardless of whether '-S' is
264
+ job_unref_locked(&job->job);
333
-# used. The intention is for a management tool to query the block devices to
265
+ job_unlock();
334
-# determine which ones are encrypted, set the passwords with this command, and
266
aio_context_release(aio_context);
335
-# then start the guest with the @cont command.
267
336
-#
268
/* publish completion progress only when success */
337
-# Either @device or @node-name must be set but not both.
338
-#
339
-# @device: the name of the block backend device to set the password on
340
-#
341
-# @node-name: graph node name to set the password on (Since 2.0)
342
-#
343
-# @password: the password to use for the device
344
-#
345
-# Returns: nothing on success
346
-# If @device is not a valid block device, DeviceNotFound
347
-# If @device is not encrypted, DeviceNotEncrypted
348
-#
349
-# Notes: Not all block formats support encryption and some that do are not
350
-# able to validate that a password is correct. Disk corruption may
351
-# occur if an invalid password is specified.
352
-#
353
-# Since: 0.14.0
354
-#
355
-# Example:
356
-#
357
-# -> { "execute": "block_passwd", "arguments": { "device": "ide0-hd0",
358
-# "password": "12345" } }
359
-# <- { "return": {} }
360
+# This command is now obsolete and will always return an error since 2.10
361
#
362
##
363
{ 'command': 'block_passwd', 'data': {'*device': 'str',
364
diff --git a/qapi/common.json b/qapi/common.json
365
index XXXXXXX..XXXXXXX 100644
366
--- a/qapi/common.json
367
+++ b/qapi/common.json
368
@@ -XXX,XX +XXX,XX @@
369
#
370
# @CommandNotFound: the requested command has not been found
371
#
372
-# @DeviceEncrypted: the requested operation can't be fulfilled because the
373
-# selected device is encrypted
374
-#
375
# @DeviceNotActive: a device has failed to be become active
376
#
377
# @DeviceNotFound: the requested device has not been found
378
@@ -XXX,XX +XXX,XX @@
379
##
380
{ 'enum': 'QapiErrorClass',
381
# Keep this in sync with ErrorClass in error.h
382
- 'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
383
+ 'data': [ 'GenericError', 'CommandNotFound',
384
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
385
386
##
387
--
269
--
388
1.8.3.1
270
2.37.3
389
390
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
More specifically, create short name from filename and change blacklist of
3
We want to make sure access of job->aio_context is always done
4
invalid chars to whitelist of valid chars.
4
under either BQL or job_mutex. The problem is that using
5
aio_co_enter(job->aiocontext, job->co) in job_start and job_enter_cond
6
makes the coroutine immediately resume, so we can't hold the job lock.
7
And caching it is not safe either, as it might change.
5
8
6
Windows 9x also now correctly see long file names of filenames containing a space,
9
job_start is under BQL, so it can freely read job->aiocontext, but
7
but Scandisk still complains about mismatch between SFN and LFN.
10
job_enter_cond is not.
11
We want to avoid reading job->aio_context in job_enter_cond, therefore:
12
1) use aio_co_wake(), since it doesn't want an aiocontext as argument
13
but uses job->co->ctx
14
2) detect possible discrepancy between job->co->ctx and job->aio_context
15
by checking right after the coroutine resumes back from yielding if
16
job->aio_context has changed. If so, reschedule the coroutine to the
17
new context.
8
18
9
[kwolf: Build fix for this intermediate patch (it included declarations
19
Calling bdrv_try_set_aio_context() will issue the following calls
10
for variables that are only used in the next patch) ]
20
(simplified):
21
* in terms of bdrv callbacks:
22
.drained_begin -> .set_aio_context -> .drained_end
23
* in terms of child_job functions:
24
child_job_drained_begin -> child_job_set_aio_context -> child_job_drained_end
25
* in terms of job functions:
26
job_pause_locked -> job_set_aio_context -> job_resume_locked
11
27
12
Specification: "FAT: General overview of on-disk format" v1.03, pages 30-31
28
We can see that after setting the new aio_context, job_resume_locked
13
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
29
calls again job_enter_cond, which then invokes aio_co_wake(). But
30
while job->aiocontext has been set in job_set_aio_context,
31
job->co->ctx has not changed, so the coroutine would be entering in
32
the wrong aiocontext.
33
34
Using aio_co_schedule in job_resume_locked() might seem as a valid
35
alternative, but the problem is that the bh resuming the coroutine
36
is not scheduled immediately, and if in the meanwhile another
37
bdrv_try_set_aio_context() is run (see test_propagate_mirror() in
38
test-block-iothread.c), we would have the first schedule in the
39
wrong aiocontext, and the second set of drains won't even manage
40
to schedule the coroutine, as job->busy would still be true from
41
the previous job_resume_locked().
42
43
The solution is to stick with aio_co_wake() and detect every time
44
the coroutine resumes back from yielding if job->aio_context
45
has changed. If so, we can reschedule it to the new context.
46
47
Check for the aiocontext change in job_do_yield_locked because:
48
1) aio_co_reschedule_self requires to be in the running coroutine
49
2) since child_job_set_aio_context allows changing the aiocontext only
50
while the job is paused, this is the exact place where the coroutine
51
resumes, before running JobDriver's code.
52
53
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
54
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
55
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
56
Message-Id: <20220926093214.506243-13-eesposit@redhat.com>
57
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
58
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
59
---
16
block/vvfat.c | 104 ++++++++++++++++++++++++++++++++++++++++++----------------
60
job.c | 19 +++++++++++++++++--
17
1 file changed, 76 insertions(+), 28 deletions(-)
61
1 file changed, 17 insertions(+), 2 deletions(-)
18
62
19
diff --git a/block/vvfat.c b/block/vvfat.c
63
diff --git a/job.c b/job.c
20
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
21
--- a/block/vvfat.c
65
--- a/job.c
22
+++ b/block/vvfat.c
66
+++ b/job.c
23
@@ -XXX,XX +XXX,XX @@ static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
67
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
24
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
68
job->busy = true;
69
real_job_unlock();
70
job_unlock();
71
- aio_co_enter(job->aio_context, job->co);
72
+ aio_co_wake(job->co);
73
job_lock();
25
}
74
}
26
75
27
+static uint8_t to_valid_short_char(gunichar c)
76
@@ -XXX,XX +XXX,XX @@ void job_enter(Job *job)
28
+{
77
*/
29
+ c = g_unichar_toupper(c);
78
static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
30
+ if ((c >= '0' && c <= '9') ||
79
{
31
+ (c >= 'A' && c <= 'Z') ||
80
+ AioContext *next_aio_context;
32
+ strchr("$%'-_@~`!(){}^#&", c) != 0) {
33
+ return c;
34
+ } else {
35
+ return 0;
36
+ }
37
+}
38
+
81
+
39
+static direntry_t *create_short_filename(BDRVVVFATState *s,
82
real_job_lock();
40
+ const char *filename)
83
if (ns != -1) {
41
+{
84
timer_mod(&job->sleep_timer, ns);
42
+ int j = 0;
85
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
43
+ direntry_t *entry = array_get_next(&(s->directory));
86
qemu_coroutine_yield();
44
+ const gchar *p, *last_dot = NULL;
87
job_lock();
45
+ gunichar c;
88
46
+ bool lossy_conversion = false;
89
- /* Set by job_enter_cond() before re-entering the coroutine. */
47
+
90
+ next_aio_context = job->aio_context;
48
+ if (!entry) {
91
+ /*
49
+ return NULL;
92
+ * Coroutine has resumed, but in the meanwhile the job AioContext
50
+ }
93
+ * might have changed via bdrv_try_set_aio_context(), so we need to move
51
+ memset(entry->name, 0x20, sizeof(entry->name));
94
+ * the coroutine too in the new aiocontext.
52
+
95
+ */
53
+ /* copy filename and search last dot */
96
+ while (qemu_get_current_aio_context() != next_aio_context) {
54
+ for (p = filename; ; p = g_utf8_next_char(p)) {
97
+ job_unlock();
55
+ c = g_utf8_get_char(p);
98
+ aio_co_reschedule_self(next_aio_context);
56
+ if (c == '\0') {
99
+ job_lock();
57
+ break;
100
+ next_aio_context = job->aio_context;
58
+ } else if (c == '.') {
59
+ if (j == 0) {
60
+ /* '.' at start of filename */
61
+ lossy_conversion = true;
62
+ } else {
63
+ if (last_dot) {
64
+ lossy_conversion = true;
65
+ }
66
+ last_dot = p;
67
+ }
68
+ } else if (!last_dot) {
69
+ /* first part of the name; copy it */
70
+ uint8_t v = to_valid_short_char(c);
71
+ if (j < 8 && v) {
72
+ entry->name[j++] = v;
73
+ } else {
74
+ lossy_conversion = true;
75
+ }
76
+ }
77
+ }
101
+ }
78
+
102
+
79
+ /* copy extension (if any) */
103
+ /* Set by job_enter_cond_locked() before re-entering the coroutine. */
80
+ if (last_dot) {
104
assert(job->busy);
81
+ j = 0;
105
}
82
+ for (p = g_utf8_next_char(last_dot); ; p = g_utf8_next_char(p)) {
106
83
+ c = g_utf8_get_char(p);
84
+ if (c == '\0') {
85
+ break;
86
+ } else {
87
+ /* extension; copy it */
88
+ uint8_t v = to_valid_short_char(c);
89
+ if (j < 3 && v) {
90
+ entry->name[8 + (j++)] = v;
91
+ } else {
92
+ lossy_conversion = true;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ (void)lossy_conversion;
98
+ return entry;
99
+}
100
+
101
/* fat functions */
102
103
static inline uint8_t fat_chksum(const direntry_t* entry)
104
@@ -XXX,XX +XXX,XX @@ static inline void init_fat(BDRVVVFATState* s)
105
static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
106
unsigned int directory_start, const char* filename, int is_dot)
107
{
108
- int i,j,long_index=s->directory.next;
109
+ int long_index = s->directory.next;
110
direntry_t* entry = NULL;
111
direntry_t* entry_long = NULL;
112
113
@@ -XXX,XX +XXX,XX @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
114
}
115
116
entry_long=create_long_filename(s,filename);
117
-
118
- i = strlen(filename);
119
- for(j = i - 1; j>0 && filename[j]!='.';j--);
120
- if (j > 0)
121
- i = (j > 8 ? 8 : j);
122
- else if (i > 8)
123
- i = 8;
124
-
125
- entry=array_get_next(&(s->directory));
126
- memset(entry->name, 0x20, sizeof(entry->name));
127
- memcpy(entry->name, filename, i);
128
-
129
- if (j > 0) {
130
- for (i = 0; i < 3 && filename[j + 1 + i]; i++) {
131
- entry->name[8 + i] = filename[j + 1 + i];
132
- }
133
- }
134
-
135
- /* upcase & remove unwanted characters */
136
- for(i=10;i>=0;i--) {
137
- if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);
138
- if(entry->name[i]<=' ' || entry->name[i]>0x7f
139
- || strchr(".*?<>|\":/\\[];,+='",entry->name[i]))
140
- entry->name[i]='_';
141
- else if(entry->name[i]>='a' && entry->name[i]<='z')
142
- entry->name[i]+='A'-'a';
143
- }
144
+ entry = create_short_filename(s, filename);
145
146
/* mangle duplicates */
147
while(1) {
148
--
107
--
149
1.8.3.1
108
2.37.3
150
151
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
In order to make it thread safe, implement a "fake rwlock",
4
easier to reason about than sector-based. Continue by converting
4
where we allow reads under BQL *or* job_mutex held, but
5
the public interface to backup jobs (no semantic change), including
5
writes only under BQL *and* job_mutex.
6
a change to CowRequest to track by bytes instead of cluster indices.
7
6
8
Note that this does not change the difference between the public
7
The only write we have is in child_job_set_aio_ctx, which always
9
interface (starting point, and size of the subsequent range) and
8
happens under drain (so the job is paused).
10
the internal interface (starting and end points).
9
For this reason, introduce job_set_aio_context and make sure that
10
the context is set under BQL, job_mutex and drain.
11
Also make sure all other places where the aiocontext is read
12
are protected.
11
13
12
Signed-off-by: Eric Blake <eblake@redhat.com>
14
The reads in commit.c and mirror.c are actually safe, because always
13
Reviewed-by: John Snow <jsnow@redhat.com>
15
done under BQL.
14
Reviewed-by: Xie Changlong <xiechanglong@cmss.chinamobile.com>
16
15
Reviewed-by: Jeff Cody <jcody@redhat.com>
17
Note: at this stage, job_{lock/unlock} and job lock guard macros
18
are *nop*.
19
20
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
21
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
22
Message-Id: <20220926093214.506243-14-eesposit@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
23
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
24
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
26
---
19
block/backup.c | 31 +++++++++++++++----------------
27
include/qemu/job.h | 23 ++++++++++++++++++++---
20
block/replication.c | 12 ++++++++----
28
block/replication.c | 1 +
21
include/block/block_backup.h | 11 +++++------
29
blockjob.c | 3 ++-
22
3 files changed, 28 insertions(+), 26 deletions(-)
30
job.c | 12 ++++++++++++
31
4 files changed, 35 insertions(+), 4 deletions(-)
23
32
24
diff --git a/block/backup.c b/block/backup.c
33
diff --git a/include/qemu/job.h b/include/qemu/job.h
25
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
26
--- a/block/backup.c
35
--- a/include/qemu/job.h
27
+++ b/block/backup.c
36
+++ b/include/qemu/job.h
28
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
37
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
29
do {
38
/* ProgressMeter API is thread-safe */
30
retry = false;
39
ProgressMeter progress;
31
QLIST_FOREACH(req, &job->inflight_reqs, list) {
40
32
- if (end > req->start && start < req->end) {
41
+ /**
33
+ if (end > req->start_byte && start < req->end_byte) {
42
+ * AioContext to run the job coroutine in.
34
qemu_co_queue_wait(&req->wait_queue, NULL);
43
+ * The job Aiocontext can be read when holding *either*
35
retry = true;
44
+ * the BQL (so we are in the main loop) or the job_mutex.
36
break;
45
+ * It can only be written when we hold *both* BQL
37
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
46
+ * and the job_mutex.
38
47
+ */
39
/* Keep track of an in-flight request */
48
+ AioContext *aio_context;
40
static void cow_request_begin(CowRequest *req, BackupBlockJob *job,
49
41
- int64_t start, int64_t end)
50
- /** Protected by AioContext lock */
42
+ int64_t start, int64_t end)
51
43
{
52
- /** AioContext to run the job coroutine in */
44
- req->start = start;
53
- AioContext *aio_context;
45
- req->end = end;
54
+ /** Protected by AioContext lock */
46
+ req->start_byte = start;
55
47
+ req->end_byte = end;
56
/** Reference count of the block job */
48
qemu_co_queue_init(&req->wait_queue);
57
int refcnt;
49
QLIST_INSERT_HEAD(&job->inflight_reqs, req, list);
58
@@ -XXX,XX +XXX,XX @@ int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
50
}
59
int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
51
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
60
Error **errp);
52
sector_num * BDRV_SECTOR_SIZE,
61
53
nb_sectors * BDRV_SECTOR_SIZE);
62
+/**
54
63
+ * Sets the @job->aio_context.
55
- wait_for_overlapping_requests(job, start, end);
64
+ * Called with job_mutex *not* held.
56
- cow_request_begin(&cow_request, job, start, end);
65
+ *
57
+ wait_for_overlapping_requests(job, start * job->cluster_size,
66
+ * This function must run in the main thread to protect against
58
+ end * job->cluster_size);
67
+ * concurrent read in job_finish_sync_locked(), takes the job_mutex
59
+ cow_request_begin(&cow_request, job, start * job->cluster_size,
68
+ * lock to protect against the read in job_do_yield_locked(), and must
60
+ end * job->cluster_size);
69
+ * be called when the job is quiescent.
61
70
+ */
62
for (; start < end; start++) {
71
+void job_set_aio_context(Job *job, AioContext *ctx);
63
if (test_bit(start, job->done_bitmap)) {
72
+
64
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
73
#endif
65
bitmap_zero(backup_job->done_bitmap, len);
66
}
67
68
-void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num,
69
- int nb_sectors)
70
+void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
71
+ uint64_t bytes)
72
{
73
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
74
- int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
75
int64_t start, end;
76
77
assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
78
79
- start = sector_num / sectors_per_cluster;
80
- end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
81
+ start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
82
+ end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
83
wait_for_overlapping_requests(backup_job, start, end);
84
}
85
86
void backup_cow_request_begin(CowRequest *req, BlockJob *job,
87
- int64_t sector_num,
88
- int nb_sectors)
89
+ int64_t offset, uint64_t bytes)
90
{
91
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
92
- int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
93
int64_t start, end;
94
95
assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
96
97
- start = sector_num / sectors_per_cluster;
98
- end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
99
+ start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
100
+ end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
101
cow_request_begin(req, backup_job, start, end);
102
}
103
104
diff --git a/block/replication.c b/block/replication.c
74
diff --git a/block/replication.c b/block/replication.c
105
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
106
--- a/block/replication.c
76
--- a/block/replication.c
107
+++ b/block/replication.c
77
+++ b/block/replication.c
108
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
78
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
79
{
80
BDRVReplicationState *s = bs->opaque;
81
Job *commit_job;
82
+ GLOBAL_STATE_CODE();
83
84
if (s->stage == BLOCK_REPLICATION_RUNNING) {
85
replication_stop(s->rs, false, NULL);
86
diff --git a/blockjob.c b/blockjob.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/blockjob.c
89
+++ b/blockjob.c
90
@@ -XXX,XX +XXX,XX @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
91
bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
109
}
92
}
110
93
111
if (job) {
94
- job->job.aio_context = ctx;
112
- backup_wait_for_overlapping_requests(child->bs->job, sector_num,
95
+ job_set_aio_context(&job->job, ctx);
113
- remaining_sectors);
96
}
114
- backup_cow_request_begin(&req, child->bs->job, sector_num,
97
115
- remaining_sectors);
98
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
116
+ uint64_t remaining_bytes = remaining_sectors * BDRV_SECTOR_SIZE;
99
{
100
BlockJob *job = c->opaque;
101
+ GLOBAL_STATE_CODE();
102
103
return job->job.aio_context;
104
}
105
diff --git a/job.c b/job.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/job.c
108
+++ b/job.c
109
@@ -XXX,XX +XXX,XX @@ Job *job_get(const char *id)
110
return job_get_locked(id);
111
}
112
113
+void job_set_aio_context(Job *job, AioContext *ctx)
114
+{
115
+ /* protect against read in job_finish_sync_locked and job_start */
116
+ GLOBAL_STATE_CODE();
117
+ /* protect against read in job_do_yield_locked */
118
+ JOB_LOCK_GUARD();
119
+ /* ensure the job is quiescent while the AioContext is changed */
120
+ assert(job->paused || job_is_completed_locked(job));
121
+ job->aio_context = ctx;
122
+}
117
+
123
+
118
+ backup_wait_for_overlapping_requests(child->bs->job,
124
/* Called with job_mutex *not* held. */
119
+ sector_num * BDRV_SECTOR_SIZE,
125
static void job_sleep_timer_cb(void *opaque)
120
+ remaining_bytes);
126
{
121
+ backup_cow_request_begin(&req, child->bs->job,
127
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
122
+ sector_num * BDRV_SECTOR_SIZE,
128
{
123
+ remaining_bytes);
129
Error *local_err = NULL;
124
ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors,
130
int ret;
125
qiov);
131
+ GLOBAL_STATE_CODE();
126
backup_cow_request_end(&req);
132
127
diff --git a/include/block/block_backup.h b/include/block/block_backup.h
133
job_ref_locked(job);
128
index XXXXXXX..XXXXXXX 100644
134
129
--- a/include/block/block_backup.h
130
+++ b/include/block/block_backup.h
131
@@ -XXX,XX +XXX,XX @@
132
#include "block/block_int.h"
133
134
typedef struct CowRequest {
135
- int64_t start;
136
- int64_t end;
137
+ int64_t start_byte;
138
+ int64_t end_byte;
139
QLIST_ENTRY(CowRequest) list;
140
CoQueue wait_queue; /* coroutines blocked on this request */
141
} CowRequest;
142
143
-void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num,
144
- int nb_sectors);
145
+void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
146
+ uint64_t bytes);
147
void backup_cow_request_begin(CowRequest *req, BlockJob *job,
148
- int64_t sector_num,
149
- int nb_sectors);
150
+ int64_t offset, uint64_t bytes);
151
void backup_cow_request_end(CowRequest *req);
152
153
void backup_do_checkpoint(BlockJob *job, Error **errp);
154
--
135
--
155
1.8.3.1
136
2.37.3
156
157
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
stream_complete() skips the work of rewriting the backing file if
3
The same job lock is being used also to protect some of blockjob fields.
4
the job was cancelled, if data->reached_end is false, or if there
4
Categorize them just as done in job.h.
5
was an error detected (non-zero data->ret) during the streaming.
6
But note that in stream_run(), data->reached_end is only set if the
7
loop ran to completion, and data->ret is only 0 in two cases:
8
either the loop ran to completion (possibly by cancellation, but
9
stream_complete checks for that), or we took an early goto out
10
because there is no bs->backing. Thus, we can preserve the same
11
semantics without the use of reached_end, by merely checking for
12
bs->backing (and logically, if there was no backing file, streaming
13
is a no-op, so there is no backing file to rewrite).
14
5
15
Suggested-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
16
Signed-off-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
17
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20220926093214.506243-15-eesposit@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
11
---
21
block/stream.c | 4 +---
12
include/block/blockjob.h | 32 ++++++++++++++++++++++++++------
22
1 file changed, 1 insertion(+), 3 deletions(-)
13
1 file changed, 26 insertions(+), 6 deletions(-)
23
14
24
diff --git a/block/stream.c b/block/stream.c
15
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/block/stream.c
17
--- a/include/block/blockjob.h
27
+++ b/block/stream.c
18
+++ b/include/block/blockjob.h
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn stream_populate(BlockBackend *blk,
19
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJobDriver BlockJobDriver;
29
20
* Long-running operation on a BlockDriverState.
30
typedef struct {
21
*/
31
int ret;
22
typedef struct BlockJob {
32
- bool reached_end;
23
- /** Data belonging to the generic Job infrastructure */
33
} StreamCompleteData;
24
+ /**
34
25
+ * Data belonging to the generic Job infrastructure.
35
static void stream_complete(BlockJob *job, void *opaque)
26
+ * Protected by job mutex.
36
@@ -XXX,XX +XXX,XX @@ static void stream_complete(BlockJob *job, void *opaque)
27
+ */
37
BlockDriverState *base = s->base;
28
Job job;
38
Error *local_err = NULL;
29
39
30
- /** Status that is published by the query-block-jobs QMP API */
40
- if (!block_job_is_cancelled(&s->common) && data->reached_end &&
31
+ /**
41
+ if (!block_job_is_cancelled(&s->common) && bs->backing &&
32
+ * Status that is published by the query-block-jobs QMP API.
42
data->ret == 0) {
33
+ * Protected by job mutex.
43
const char *base_id = NULL, *base_fmt = NULL;
34
+ */
44
if (base) {
35
BlockDeviceIoStatus iostatus;
45
@@ -XXX,XX +XXX,XX @@ out:
36
46
/* Modify backing chain and close BDSes in main loop */
37
- /** Speed that was set with @block_job_set_speed. */
47
data = g_malloc(sizeof(*data));
38
+ /**
48
data->ret = ret;
39
+ * Speed that was set with @block_job_set_speed.
49
- data->reached_end = sector_num == end;
40
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
50
block_job_defer_to_main_loop(&s->common, stream_complete, data);
41
+ */
51
}
42
int64_t speed;
43
44
- /** Rate limiting data structure for implementing @speed. */
45
+ /**
46
+ * Rate limiting data structure for implementing @speed.
47
+ * RateLimit API is thread-safe.
48
+ */
49
RateLimit limit;
50
51
- /** Block other operations when block job is running */
52
+ /**
53
+ * Block other operations when block job is running.
54
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
55
+ */
56
Error *blocker;
57
58
+ /** All notifiers are set once in block_job_create() and never modified. */
59
+
60
/** Called when a cancelled job is finalised. */
61
Notifier finalize_cancelled_notifier;
62
63
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
64
/** Called when the job coroutine yields or terminates */
65
Notifier idle_notifier;
66
67
- /** BlockDriverStates that are involved in this block job */
68
+ /**
69
+ * BlockDriverStates that are involved in this block job.
70
+ * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE).
71
+ */
72
GSList *nodes;
73
} BlockJob;
52
74
53
--
75
--
54
1.8.3.1
76
2.37.3
55
56
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This converts the qcow2 driver to make use of the QCryptoBlock
3
They all are called with job_lock held, in job_event_*_locked()
4
APIs for encrypting image content, using the legacy QCow2 AES
5
scheme.
6
4
7
With this change it is now required to use the QCryptoSecret
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
object for providing passwords, instead of the current block
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
password APIs / interactive prompting.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20220926093214.506243-16-eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
blockjob.c | 25 +++++++++++++++----------
13
1 file changed, 15 insertions(+), 10 deletions(-)
10
14
11
$QEMU \
15
diff --git a/blockjob.c b/blockjob.c
12
-object secret,id=sec0,file=/home/berrange/encrypted.pw \
13
-drive file=/home/berrange/encrypted.qcow2,encrypt.key-secret=sec0
14
15
The test 087 could be simplified since there is no longer a
16
difference in behaviour when using blockdev_add with encrypted
17
images for the running vs stopped CPU state.
18
19
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
20
Message-id: 20170623162419.26068-12-berrange@redhat.com
21
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
block/qcow2-cluster.c | 47 +---------
25
block/qcow2.c | 226 ++++++++++++++++++++++++++++++---------------
26
block/qcow2.h | 5 +-
27
qapi/block-core.json | 27 +++++-
28
tests/qemu-iotests/049 | 2 +-
29
tests/qemu-iotests/049.out | 4 +-
30
tests/qemu-iotests/082.out | 27 ++++++
31
tests/qemu-iotests/087 | 28 +++---
32
tests/qemu-iotests/087.out | 12 +--
33
tests/qemu-iotests/134 | 18 +++-
34
tests/qemu-iotests/134.out | 10 +-
35
tests/qemu-iotests/158 | 19 ++--
36
tests/qemu-iotests/158.out | 14 +--
37
tests/qemu-iotests/common | 10 +-
38
14 files changed, 263 insertions(+), 186 deletions(-)
39
40
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
41
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
42
--- a/block/qcow2-cluster.c
17
--- a/blockjob.c
43
+++ b/block/qcow2-cluster.c
18
+++ b/blockjob.c
44
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters_unallocated(int nb_clusters,
19
@@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
45
return i;
20
return 0;
46
}
21
}
47
22
48
-/* The crypt function is compatible with the linux cryptoloop
23
-static void block_job_on_idle(Notifier *n, void *opaque)
49
- algorithm for < 4 GB images. */
24
+/* Called with job_mutex lock held. */
50
-int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
25
+static void block_job_on_idle_locked(Notifier *n, void *opaque)
51
- uint8_t *buf, int nb_sectors, bool enc,
26
{
52
- Error **errp)
27
aio_wait_kick();
53
-{
28
}
54
- union {
29
@@ -XXX,XX +XXX,XX @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
55
- uint64_t ll[2];
56
- uint8_t b[16];
57
- } ivec;
58
- int i;
59
- int ret;
60
-
61
- for(i = 0; i < nb_sectors; i++) {
62
- ivec.ll[0] = cpu_to_le64(sector_num);
63
- ivec.ll[1] = 0;
64
- if (qcrypto_cipher_setiv(s->cipher,
65
- ivec.b, G_N_ELEMENTS(ivec.b),
66
- errp) < 0) {
67
- return -1;
68
- }
69
- if (enc) {
70
- ret = qcrypto_cipher_encrypt(s->cipher,
71
- buf, buf,
72
- 512,
73
- errp);
74
- } else {
75
- ret = qcrypto_cipher_decrypt(s->cipher,
76
- buf, buf,
77
- 512,
78
- errp);
79
- }
80
- if (ret < 0) {
81
- return -1;
82
- }
83
- sector_num++;
84
- buf += 512;
85
- }
86
- return 0;
87
-}
88
-
89
static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
90
uint64_t src_cluster_offset,
91
unsigned offset_in_cluster,
92
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
93
BDRVQcow2State *s = bs->opaque;
94
int64_t sector = (src_cluster_offset + offset_in_cluster)
95
>> BDRV_SECTOR_BITS;
96
- assert(s->cipher);
97
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
98
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
99
- if (qcow2_encrypt_sectors(s, sector, buffer,
100
- bytes >> BDRV_SECTOR_BITS, true, NULL) < 0) {
101
+ assert(s->crypto);
102
+ if (qcrypto_block_encrypt(s->crypto, sector, buffer,
103
+ bytes, NULL) < 0) {
104
return false;
105
}
106
}
30
}
107
diff --git a/block/qcow2.c b/block/qcow2.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/block/qcow2.c
110
+++ b/block/qcow2.c
111
@@ -XXX,XX +XXX,XX @@
112
#include "qemu/option_int.h"
113
#include "qemu/cutils.h"
114
#include "qemu/bswap.h"
115
+#include "qapi/opts-visitor.h"
116
+#include "qapi-visit.h"
117
+#include "block/crypto.h"
118
119
/*
120
Differences with QCOW:
121
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_runtime_opts = {
122
.type = QEMU_OPT_NUMBER,
123
.help = "Clean unused cache entries after this time (in seconds)",
124
},
125
+ BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
126
{ /* end of list */ }
127
},
128
};
129
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2ReopenState {
130
int overlap_check;
131
bool discard_passthrough[QCOW2_DISCARD_MAX];
132
uint64_t cache_clean_interval;
133
+ QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
134
} Qcow2ReopenState;
135
136
static int qcow2_update_options_prepare(BlockDriverState *bs,
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
138
int overlap_check_template = 0;
139
uint64_t l2_cache_size, refcount_cache_size;
140
int i;
141
+ const char *encryptfmt;
142
+ QDict *encryptopts = NULL;
143
Error *local_err = NULL;
144
int ret;
145
146
+ qdict_extract_subqdict(options, &encryptopts, "encrypt.");
147
+ encryptfmt = qdict_get_try_str(encryptopts, "format");
148
+
149
opts = qemu_opts_create(&qcow2_runtime_opts, NULL, 0, &error_abort);
150
qemu_opts_absorb_qdict(opts, options, &local_err);
151
if (local_err) {
152
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
153
r->discard_passthrough[QCOW2_DISCARD_OTHER] =
154
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
155
156
+ switch (s->crypt_method_header) {
157
+ case QCOW_CRYPT_NONE:
158
+ if (encryptfmt) {
159
+ error_setg(errp, "No encryption in image header, but options "
160
+ "specified format '%s'", encryptfmt);
161
+ ret = -EINVAL;
162
+ goto fail;
163
+ }
164
+ break;
165
+
166
+ case QCOW_CRYPT_AES:
167
+ if (encryptfmt && !g_str_equal(encryptfmt, "aes")) {
168
+ error_setg(errp,
169
+ "Header reported 'aes' encryption format but "
170
+ "options specify '%s'", encryptfmt);
171
+ ret = -EINVAL;
172
+ goto fail;
173
+ }
174
+ qdict_del(encryptopts, "format");
175
+ r->crypto_opts = block_crypto_open_opts_init(
176
+ Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
177
+ break;
178
+
179
+ default:
180
+ error_setg(errp, "Unsupported encryption method %d",
181
+ s->crypt_method_header);
182
+ break;
183
+ }
184
+ if (s->crypt_method_header != QCOW_CRYPT_NONE && !r->crypto_opts) {
185
+ ret = -EINVAL;
186
+ goto fail;
187
+ }
188
+
189
ret = 0;
190
fail:
191
+ QDECREF(encryptopts);
192
qemu_opts_del(opts);
193
opts = NULL;
194
return ret;
195
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_commit(BlockDriverState *bs,
196
s->cache_clean_interval = r->cache_clean_interval;
197
cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
198
}
199
+
200
+ qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
201
+ s->crypto_opts = r->crypto_opts;
202
}
31
}
203
32
204
static void qcow2_update_options_abort(BlockDriverState *bs,
33
-static void block_job_event_cancelled(Notifier *n, void *opaque)
205
@@ -XXX,XX +XXX,XX @@ static void qcow2_update_options_abort(BlockDriverState *bs,
34
+/* Called with job_mutex lock held. */
206
if (r->refcount_block_cache) {
35
+static void block_job_event_cancelled_locked(Notifier *n, void *opaque)
207
qcow2_cache_destroy(bs, r->refcount_block_cache);
36
{
208
}
37
BlockJob *job = opaque;
209
+ qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
38
uint64_t progress_current, progress_total;
39
@@ -XXX,XX +XXX,XX @@ static void block_job_event_cancelled(Notifier *n, void *opaque)
40
job->speed);
210
}
41
}
211
42
212
static int qcow2_update_options(BlockDriverState *bs, QDict *options,
43
-static void block_job_event_completed(Notifier *n, void *opaque)
213
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
44
+/* Called with job_mutex lock held. */
214
ret = -EINVAL;
45
+static void block_job_event_completed_locked(Notifier *n, void *opaque)
215
goto fail;
46
{
216
}
47
BlockJob *job = opaque;
217
- if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128,
48
const char *msg = NULL;
218
- QCRYPTO_CIPHER_MODE_CBC)) {
49
@@ -XXX,XX +XXX,XX @@ static void block_job_event_completed(Notifier *n, void *opaque)
219
- error_setg(errp, "AES cipher not available");
50
msg);
220
- ret = -EINVAL;
221
- goto fail;
222
- }
223
s->crypt_method_header = header.crypt_method;
224
if (s->crypt_method_header) {
225
if (bdrv_uses_whitelist() &&
226
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
227
}
228
229
bs->encrypted = true;
230
+ bs->valid_key = true;
231
}
232
233
s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
234
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
235
goto fail;
236
}
237
238
+ if (s->crypt_method_header == QCOW_CRYPT_AES) {
239
+ unsigned int cflags = 0;
240
+ if (flags & BDRV_O_NO_IO) {
241
+ cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
242
+ }
243
+ s->crypto = qcrypto_block_open(s->crypto_opts, NULL, NULL,
244
+ cflags, errp);
245
+ if (!s->crypto) {
246
+ ret = -EINVAL;
247
+ goto fail;
248
+ }
249
+ }
250
+
251
/* read the backing file name */
252
if (header.backing_file_offset != 0) {
253
len = header.backing_file_size;
254
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
255
}
256
g_free(s->cluster_cache);
257
qemu_vfree(s->cluster_data);
258
+ qcrypto_block_free(s->crypto);
259
+ qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
260
return ret;
261
}
51
}
262
52
263
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
53
-static void block_job_event_pending(Notifier *n, void *opaque)
264
bs->bl.pdiscard_alignment = s->cluster_size;
54
+/* Called with job_mutex lock held. */
55
+static void block_job_event_pending_locked(Notifier *n, void *opaque)
56
{
57
BlockJob *job = opaque;
58
59
@@ -XXX,XX +XXX,XX @@ static void block_job_event_pending(Notifier *n, void *opaque)
60
job->job.id);
265
}
61
}
266
62
267
-static int qcow2_set_key(BlockDriverState *bs, const char *key)
63
-static void block_job_event_ready(Notifier *n, void *opaque)
268
-{
64
+/* Called with job_mutex lock held. */
269
- BDRVQcow2State *s = bs->opaque;
65
+static void block_job_event_ready_locked(Notifier *n, void *opaque)
270
- uint8_t keybuf[16];
271
- int len, i;
272
- Error *err = NULL;
273
-
274
- memset(keybuf, 0, 16);
275
- len = strlen(key);
276
- if (len > 16)
277
- len = 16;
278
- /* XXX: we could compress the chars to 7 bits to increase
279
- entropy */
280
- for(i = 0;i < len;i++) {
281
- keybuf[i] = key[i];
282
- }
283
- assert(bs->encrypted);
284
-
285
- qcrypto_cipher_free(s->cipher);
286
- s->cipher = qcrypto_cipher_new(
287
- QCRYPTO_CIPHER_ALG_AES_128,
288
- QCRYPTO_CIPHER_MODE_CBC,
289
- keybuf, G_N_ELEMENTS(keybuf),
290
- &err);
291
-
292
- if (!s->cipher) {
293
- /* XXX would be nice if errors in this method could
294
- * be properly propagate to the caller. Would need
295
- * the bdrv_set_key() API signature to be fixed. */
296
- error_free(err);
297
- return -1;
298
- }
299
- return 0;
300
-}
301
-
302
static int qcow2_reopen_prepare(BDRVReopenState *state,
303
BlockReopenQueue *queue, Error **errp)
304
{
66
{
305
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
67
BlockJob *job = opaque;
306
*pnum = bytes >> BDRV_SECTOR_BITS;
68
uint64_t progress_current, progress_total;
307
69
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
308
if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
70
309
- !s->cipher) {
71
ratelimit_init(&job->limit);
310
+ !s->crypto) {
72
311
index_in_cluster = sector_num & (s->cluster_sectors - 1);
73
- job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
312
cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
74
- job->finalize_completed_notifier.notify = block_job_event_completed;
313
*file = bs->file->bs;
75
- job->pending_notifier.notify = block_job_event_pending;
314
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
76
- job->ready_notifier.notify = block_job_event_ready;
315
77
- job->idle_notifier.notify = block_job_on_idle;
316
/* prepare next request */
78
+ job->finalize_cancelled_notifier.notify = block_job_event_cancelled_locked;
317
cur_bytes = MIN(bytes, INT_MAX);
79
+ job->finalize_completed_notifier.notify = block_job_event_completed_locked;
318
- if (s->cipher) {
80
+ job->pending_notifier.notify = block_job_event_pending_locked;
319
+ if (s->crypto) {
81
+ job->ready_notifier.notify = block_job_event_ready_locked;
320
cur_bytes = MIN(cur_bytes,
82
+ job->idle_notifier.notify = block_job_on_idle_locked;
321
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
83
322
}
84
WITH_JOB_LOCK_GUARD() {
323
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
85
notifier_list_add(&job->job.on_finalize_cancelled,
324
}
325
326
if (bs->encrypted) {
327
- assert(s->cipher);
328
+ assert(s->crypto);
329
330
/*
331
* For encrypted images, read everything into a temporary
332
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
333
goto fail;
334
}
335
if (bs->encrypted) {
336
- assert(s->cipher);
337
+ assert(s->crypto);
338
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
339
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
340
Error *err = NULL;
341
- if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS,
342
+ if (qcrypto_block_decrypt(s->crypto,
343
+ offset >> BDRV_SECTOR_BITS,
344
cluster_data,
345
- cur_bytes >> BDRV_SECTOR_BITS,
346
- false, &err) < 0) {
347
+ cur_bytes,
348
+ &err) < 0) {
349
error_free(err);
350
ret = -EIO;
351
goto fail;
352
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
353
354
if (bs->encrypted) {
355
Error *err = NULL;
356
- assert(s->cipher);
357
+ assert(s->crypto);
358
if (!cluster_data) {
359
cluster_data = qemu_try_blockalign(bs->file->bs,
360
QCOW_MAX_CRYPT_CLUSTERS
361
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
362
QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
363
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
364
365
- if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS,
366
+ if (qcrypto_block_encrypt(s->crypto, offset >> BDRV_SECTOR_BITS,
367
cluster_data,
368
- cur_bytes >>BDRV_SECTOR_BITS,
369
- true, &err) < 0) {
370
+ cur_bytes, &err) < 0) {
371
error_free(err);
372
ret = -EIO;
373
goto fail;
374
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
375
qcow2_cache_destroy(bs, s->l2_table_cache);
376
qcow2_cache_destroy(bs, s->refcount_block_cache);
377
378
- qcrypto_cipher_free(s->cipher);
379
- s->cipher = NULL;
380
+ qcrypto_block_free(s->crypto);
381
+ s->crypto = NULL;
382
383
g_free(s->unknown_header_fields);
384
cleanup_unknown_header_ext(bs);
385
@@ -XXX,XX +XXX,XX @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
386
{
387
BDRVQcow2State *s = bs->opaque;
388
int flags = s->flags;
389
- QCryptoCipher *cipher = NULL;
390
+ QCryptoBlock *crypto = NULL;
391
QDict *options;
392
Error *local_err = NULL;
393
int ret;
394
@@ -XXX,XX +XXX,XX @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
395
* that means we don't have to worry about reopening them here.
396
*/
397
398
- cipher = s->cipher;
399
- s->cipher = NULL;
400
+ crypto = s->crypto;
401
+ s->crypto = NULL;
402
403
qcow2_close(bs);
404
405
@@ -XXX,XX +XXX,XX @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
406
return;
407
}
408
409
- s->cipher = cipher;
410
+ s->crypto = crypto;
411
}
412
413
static size_t header_ext_add(char *buf, uint32_t magic, const void *s,
414
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
415
return qcow2_update_header(bs);
416
}
417
418
+
419
+static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
420
+ QemuOpts *opts, Error **errp)
421
+{
422
+ BDRVQcow2State *s = bs->opaque;
423
+ QCryptoBlockCreateOptions *cryptoopts = NULL;
424
+ QCryptoBlock *crypto = NULL;
425
+ int ret = -EINVAL;
426
+ QDict *options, *encryptopts;
427
+
428
+ options = qemu_opts_to_qdict(opts, NULL);
429
+ qdict_extract_subqdict(options, &encryptopts, "encrypt.");
430
+ QDECREF(options);
431
+
432
+ if (!g_str_equal(encryptfmt, "aes")) {
433
+ error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
434
+ encryptfmt);
435
+ ret = -EINVAL;
436
+ goto out;
437
+ }
438
+ cryptoopts = block_crypto_create_opts_init(
439
+ Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
440
+ if (!cryptoopts) {
441
+ ret = -EINVAL;
442
+ goto out;
443
+ }
444
+ s->crypt_method_header = QCOW_CRYPT_AES;
445
+
446
+ crypto = qcrypto_block_create(cryptoopts,
447
+ NULL, NULL,
448
+ bs, errp);
449
+ if (!crypto) {
450
+ ret = -EINVAL;
451
+ goto out;
452
+ }
453
+
454
+ ret = qcow2_update_header(bs);
455
+ if (ret < 0) {
456
+ error_setg_errno(errp, -ret, "Could not write encryption header");
457
+ goto out;
458
+ }
459
+
460
+ out:
461
+ QDECREF(encryptopts);
462
+ qcrypto_block_free(crypto);
463
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
464
+ return ret;
465
+}
466
+
467
+
468
static int preallocate(BlockDriverState *bs)
469
{
470
uint64_t bytes;
471
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
472
.header_length = cpu_to_be32(sizeof(*header)),
473
};
474
475
- if (encryptfmt) {
476
- if (!g_str_equal(encryptfmt, "aes")) {
477
- error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
478
- encryptfmt);
479
- ret = -EINVAL;
480
- goto out;
481
- }
482
- header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
483
- } else {
484
- header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
485
- }
486
+ /* We'll update this to correct value later */
487
+ header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
488
489
if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) {
490
header->compatible_features |=
491
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
492
}
493
}
494
495
+ /* Want encryption? There you go. */
496
+ if (encryptfmt) {
497
+ ret = qcow2_set_up_encryption(blk_bs(blk), encryptfmt, opts, errp);
498
+ if (ret < 0) {
499
+ goto out;
500
+ }
501
+ }
502
+
503
/* And if we're supposed to preallocate metadata, do that now */
504
if (prealloc != PREALLOC_MODE_OFF) {
505
BDRVQcow2State *s = blk_bs(blk)->opaque;
506
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
507
blk_unref(blk);
508
blk = NULL;
509
510
- /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
511
+ /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning.
512
+ * Using BDRV_O_NO_IO, since encryption is now setup we don't want to
513
+ * have to setup decryption context. We're not doing any I/O on the top
514
+ * level BlockDriverState, only lower layers, where BDRV_O_NO_IO does
515
+ * not have effect.
516
+ */
517
options = qdict_new();
518
qdict_put_str(options, "driver", "qcow2");
519
blk = blk_new_open(filename, NULL, options,
520
- BDRV_O_RDWR | BDRV_O_NO_BACKING, &local_err);
521
+ BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
522
+ &local_err);
523
if (blk == NULL) {
524
error_propagate(errp, local_err);
525
ret = -EIO;
526
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
527
backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
528
} else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) {
529
encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT,
530
- !!s->cipher);
531
+ !!s->crypto);
532
533
- if (encrypt != !!s->cipher) {
534
+ if (encrypt != !!s->crypto) {
535
error_report("Changing the encryption flag is not supported");
536
return -ENOTSUP;
537
}
538
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
539
.type = QEMU_OPT_STRING,
540
.help = "Encrypt the image, format choices: 'aes'",
541
},
542
+ BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
543
{
544
.name = BLOCK_OPT_CLUSTER_SIZE,
545
.type = QEMU_OPT_SIZE,
546
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
547
.bdrv_create = qcow2_create,
548
.bdrv_has_zero_init = bdrv_has_zero_init_1,
549
.bdrv_co_get_block_status = qcow2_co_get_block_status,
550
- .bdrv_set_key = qcow2_set_key,
551
552
.bdrv_co_preadv = qcow2_co_preadv,
553
.bdrv_co_pwritev = qcow2_co_pwritev,
554
diff --git a/block/qcow2.h b/block/qcow2.h
555
index XXXXXXX..XXXXXXX 100644
556
--- a/block/qcow2.h
557
+++ b/block/qcow2.h
558
@@ -XXX,XX +XXX,XX @@
559
#ifndef BLOCK_QCOW2_H
560
#define BLOCK_QCOW2_H
561
562
-#include "crypto/cipher.h"
563
+#include "crypto/block.h"
564
#include "qemu/coroutine.h"
565
566
//#define DEBUG_ALLOC
567
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
568
569
CoMutex lock;
570
571
- QCryptoCipher *cipher; /* current cipher, NULL if no key yet */
572
+ QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
573
+ QCryptoBlock *crypto; /* Disk encryption format driver */
574
uint32_t crypt_method_header;
575
uint64_t snapshots_offset;
576
int snapshots_size;
577
diff --git a/qapi/block-core.json b/qapi/block-core.json
578
index XXXXXXX..XXXXXXX 100644
579
--- a/qapi/block-core.json
580
+++ b/qapi/block-core.json
581
@@ -XXX,XX +XXX,XX @@
582
'data': { '*encrypt': 'BlockdevQcowEncryption' } }
583
584
585
+
586
+##
587
+# @BlockdevQcow2EncryptionFormat:
588
+# @aes: AES-CBC with plain64 initialization venctors
589
+#
590
+# Since: 2.10
591
+##
592
+{ 'enum': 'BlockdevQcow2EncryptionFormat',
593
+ 'data': [ 'aes' ] }
594
+
595
+##
596
+# @BlockdevQcow2Encryption:
597
+#
598
+# Since: 2.10
599
+##
600
+{ 'union': 'BlockdevQcow2Encryption',
601
+ 'base': { 'format': 'BlockdevQcow2EncryptionFormat' },
602
+ 'discriminator': 'format',
603
+ 'data': { 'aes': 'QCryptoBlockOptionsQCow' } }
604
+
605
##
606
# @BlockdevOptionsQcow2:
607
#
608
@@ -XXX,XX +XXX,XX @@
609
# @cache-clean-interval: clean unused entries in the L2 and refcount
610
# caches. The interval is in seconds. The default value
611
# is 0 and it disables this feature (since 2.5)
612
+# @encrypt: Image decryption options. Mandatory for
613
+# encrypted images, except when doing a metadata-only
614
+# probe of the image. (since 2.10)
615
#
616
# Since: 2.9
617
##
618
@@ -XXX,XX +XXX,XX @@
619
'*cache-size': 'int',
620
'*l2-cache-size': 'int',
621
'*refcount-cache-size': 'int',
622
- '*cache-clean-interval': 'int' } }
623
-
624
+ '*cache-clean-interval': 'int',
625
+ '*encrypt': 'BlockdevQcow2Encryption' } }
626
627
##
628
# @BlockdevOptionsSsh:
629
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
630
index XXXXXXX..XXXXXXX 100755
631
--- a/tests/qemu-iotests/049
632
+++ b/tests/qemu-iotests/049
633
@@ -XXX,XX +XXX,XX @@ test_qemu_img create -f $IMGFMT -o preallocation=1234 "$TEST_IMG" 64M
634
echo "== Check encryption option =="
635
echo
636
test_qemu_img create -f $IMGFMT -o encryption=off "$TEST_IMG" 64M
637
-test_qemu_img create -f $IMGFMT -o encryption=on "$TEST_IMG" 64M
638
+test_qemu_img create -f $IMGFMT --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 "$TEST_IMG" 64M
639
640
echo "== Check lazy_refcounts option (only with v3) =="
641
echo
642
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
643
index XXXXXXX..XXXXXXX 100644
644
--- a/tests/qemu-iotests/049.out
645
+++ b/tests/qemu-iotests/049.out
646
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preall
647
qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
648
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
649
650
-qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M
651
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16
652
+qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M
653
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16
654
655
== Check lazy_refcounts option (only with v3) ==
656
657
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
658
index XXXXXXX..XXXXXXX 100644
659
--- a/tests/qemu-iotests/082.out
660
+++ b/tests/qemu-iotests/082.out
661
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
662
backing_fmt Image format of the base image
663
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
664
encrypt.format Encrypt the image, format choices: 'aes'
665
+encrypt.key-secret ID of the secret that provides the AES encryption key
666
cluster_size qcow2 cluster size
667
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
668
lazy_refcounts Postpone refcount updates
669
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
670
backing_fmt Image format of the base image
671
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
672
encrypt.format Encrypt the image, format choices: 'aes'
673
+encrypt.key-secret ID of the secret that provides the AES encryption key
674
cluster_size qcow2 cluster size
675
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
676
lazy_refcounts Postpone refcount updates
677
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
678
backing_fmt Image format of the base image
679
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
680
encrypt.format Encrypt the image, format choices: 'aes'
681
+encrypt.key-secret ID of the secret that provides the AES encryption key
682
cluster_size qcow2 cluster size
683
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
684
lazy_refcounts Postpone refcount updates
685
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
686
backing_fmt Image format of the base image
687
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
688
encrypt.format Encrypt the image, format choices: 'aes'
689
+encrypt.key-secret ID of the secret that provides the AES encryption key
690
cluster_size qcow2 cluster size
691
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
692
lazy_refcounts Postpone refcount updates
693
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
694
backing_fmt Image format of the base image
695
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
696
encrypt.format Encrypt the image, format choices: 'aes'
697
+encrypt.key-secret ID of the secret that provides the AES encryption key
698
cluster_size qcow2 cluster size
699
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
700
lazy_refcounts Postpone refcount updates
701
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
702
backing_fmt Image format of the base image
703
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
704
encrypt.format Encrypt the image, format choices: 'aes'
705
+encrypt.key-secret ID of the secret that provides the AES encryption key
706
cluster_size qcow2 cluster size
707
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
708
lazy_refcounts Postpone refcount updates
709
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
710
backing_fmt Image format of the base image
711
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
712
encrypt.format Encrypt the image, format choices: 'aes'
713
+encrypt.key-secret ID of the secret that provides the AES encryption key
714
cluster_size qcow2 cluster size
715
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
716
lazy_refcounts Postpone refcount updates
717
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
718
backing_fmt Image format of the base image
719
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
720
encrypt.format Encrypt the image, format choices: 'aes'
721
+encrypt.key-secret ID of the secret that provides the AES encryption key
722
cluster_size qcow2 cluster size
723
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
724
lazy_refcounts Postpone refcount updates
725
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
726
backing_fmt Image format of the base image
727
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
728
encrypt.format Encrypt the image, format choices: 'aes'
729
+encrypt.key-secret ID of the secret that provides the AES encryption key
730
cluster_size qcow2 cluster size
731
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
732
lazy_refcounts Postpone refcount updates
733
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
734
backing_fmt Image format of the base image
735
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
736
encrypt.format Encrypt the image, format choices: 'aes'
737
+encrypt.key-secret ID of the secret that provides the AES encryption key
738
cluster_size qcow2 cluster size
739
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
740
lazy_refcounts Postpone refcount updates
741
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
742
backing_fmt Image format of the base image
743
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
744
encrypt.format Encrypt the image, format choices: 'aes'
745
+encrypt.key-secret ID of the secret that provides the AES encryption key
746
cluster_size qcow2 cluster size
747
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
748
lazy_refcounts Postpone refcount updates
749
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
750
backing_fmt Image format of the base image
751
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
752
encrypt.format Encrypt the image, format choices: 'aes'
753
+encrypt.key-secret ID of the secret that provides the AES encryption key
754
cluster_size qcow2 cluster size
755
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
756
lazy_refcounts Postpone refcount updates
757
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
758
backing_fmt Image format of the base image
759
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
760
encrypt.format Encrypt the image, format choices: 'aes'
761
+encrypt.key-secret ID of the secret that provides the AES encryption key
762
cluster_size qcow2 cluster size
763
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
764
lazy_refcounts Postpone refcount updates
765
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
766
backing_fmt Image format of the base image
767
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
768
encrypt.format Encrypt the image, format choices: 'aes'
769
+encrypt.key-secret ID of the secret that provides the AES encryption key
770
cluster_size qcow2 cluster size
771
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
772
lazy_refcounts Postpone refcount updates
773
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
774
backing_fmt Image format of the base image
775
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
776
encrypt.format Encrypt the image, format choices: 'aes'
777
+encrypt.key-secret ID of the secret that provides the AES encryption key
778
cluster_size qcow2 cluster size
779
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
780
lazy_refcounts Postpone refcount updates
781
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
782
backing_fmt Image format of the base image
783
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
784
encrypt.format Encrypt the image, format choices: 'aes'
785
+encrypt.key-secret ID of the secret that provides the AES encryption key
786
cluster_size qcow2 cluster size
787
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
788
lazy_refcounts Postpone refcount updates
789
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
790
backing_fmt Image format of the base image
791
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
792
encrypt.format Encrypt the image, format choices: 'aes'
793
+encrypt.key-secret ID of the secret that provides the AES encryption key
794
cluster_size qcow2 cluster size
795
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
796
lazy_refcounts Postpone refcount updates
797
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
798
backing_fmt Image format of the base image
799
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
800
encrypt.format Encrypt the image, format choices: 'aes'
801
+encrypt.key-secret ID of the secret that provides the AES encryption key
802
cluster_size qcow2 cluster size
803
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
804
lazy_refcounts Postpone refcount updates
805
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
806
backing_fmt Image format of the base image
807
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
808
encrypt.format Encrypt the image, format choices: 'aes'
809
+encrypt.key-secret ID of the secret that provides the AES encryption key
810
cluster_size qcow2 cluster size
811
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
812
lazy_refcounts Postpone refcount updates
813
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
814
backing_fmt Image format of the base image
815
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
816
encrypt.format Encrypt the image, format choices: 'aes'
817
+encrypt.key-secret ID of the secret that provides the AES encryption key
818
cluster_size qcow2 cluster size
819
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
820
lazy_refcounts Postpone refcount updates
821
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
822
backing_fmt Image format of the base image
823
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
824
encrypt.format Encrypt the image, format choices: 'aes'
825
+encrypt.key-secret ID of the secret that provides the AES encryption key
826
cluster_size qcow2 cluster size
827
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
828
lazy_refcounts Postpone refcount updates
829
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
830
backing_fmt Image format of the base image
831
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
832
encrypt.format Encrypt the image, format choices: 'aes'
833
+encrypt.key-secret ID of the secret that provides the AES encryption key
834
cluster_size qcow2 cluster size
835
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
836
lazy_refcounts Postpone refcount updates
837
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
838
backing_fmt Image format of the base image
839
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
840
encrypt.format Encrypt the image, format choices: 'aes'
841
+encrypt.key-secret ID of the secret that provides the AES encryption key
842
cluster_size qcow2 cluster size
843
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
844
lazy_refcounts Postpone refcount updates
845
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
846
backing_fmt Image format of the base image
847
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
848
encrypt.format Encrypt the image, format choices: 'aes'
849
+encrypt.key-secret ID of the secret that provides the AES encryption key
850
cluster_size qcow2 cluster size
851
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
852
lazy_refcounts Postpone refcount updates
853
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
854
backing_fmt Image format of the base image
855
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
856
encrypt.format Encrypt the image, format choices: 'aes'
857
+encrypt.key-secret ID of the secret that provides the AES encryption key
858
cluster_size qcow2 cluster size
859
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
860
lazy_refcounts Postpone refcount updates
861
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
862
backing_fmt Image format of the base image
863
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
864
encrypt.format Encrypt the image, format choices: 'aes'
865
+encrypt.key-secret ID of the secret that provides the AES encryption key
866
cluster_size qcow2 cluster size
867
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
868
lazy_refcounts Postpone refcount updates
869
@@ -XXX,XX +XXX,XX @@ backing_file File name of a base image
870
backing_fmt Image format of the base image
871
encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
872
encrypt.format Encrypt the image, format choices: 'aes'
873
+encrypt.key-secret ID of the secret that provides the AES encryption key
874
cluster_size qcow2 cluster size
875
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
876
lazy_refcounts Postpone refcount updates
877
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
878
index XXXXXXX..XXXXXXX 100755
879
--- a/tests/qemu-iotests/087
880
+++ b/tests/qemu-iotests/087
881
@@ -XXX,XX +XXX,XX @@ echo
882
echo === Encrypted image ===
883
echo
884
885
-_make_test_img -o encryption=on $size
886
-run_qemu -S <<EOF
887
+_make_test_img --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 $size
888
+run_qemu <<EOF
889
{ "execute": "qmp_capabilities" }
890
-{ "execute": "blockdev-add",
891
+{ "execute": "object-add",
892
"arguments": {
893
- "driver": "$IMGFMT",
894
- "node-name": "disk",
895
- "file": {
896
- "driver": "file",
897
- "filename": "$TEST_IMG"
898
+ "qom-type": "secret",
899
+ "id": "sec0",
900
+ "props": {
901
+ "data": "123456"
902
}
903
- }
904
}
905
-{ "execute": "quit" }
906
-EOF
907
-
908
-run_qemu <<EOF
909
-{ "execute": "qmp_capabilities" }
910
+}
911
{ "execute": "blockdev-add",
912
"arguments": {
913
"driver": "$IMGFMT",
914
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
915
"file": {
916
"driver": "file",
917
"filename": "$TEST_IMG"
918
+ },
919
+ "encrypt": {
920
+ "format": "aes",
921
+ "key-secret": "sec0"
922
}
923
}
924
}
925
@@ -XXX,XX +XXX,XX @@ echo
926
echo === Missing driver ===
927
echo
928
929
-_make_test_img -o encryption=on $size
930
+_make_test_img --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 $size
931
run_qemu -S <<EOF
932
{ "execute": "qmp_capabilities" }
933
{ "execute": "blockdev-add",
934
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
935
index XXXXXXX..XXXXXXX 100644
936
--- a/tests/qemu-iotests/087.out
937
+++ b/tests/qemu-iotests/087.out
938
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
939
940
=== Encrypted image ===
941
942
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
943
-Testing: -S
944
-QMP_VERSION
945
-{"return": {}}
946
-{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
947
-{"return": {}}
948
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
949
-
950
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
951
Testing:
952
QMP_VERSION
953
{"return": {}}
954
+{"return": {}}
955
{"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
956
{"return": {}}
957
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
958
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
959
960
=== Missing driver ===
961
962
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
963
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
964
Testing: -S
965
QMP_VERSION
966
{"return": {}}
967
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
968
index XXXXXXX..XXXXXXX 100755
969
--- a/tests/qemu-iotests/134
970
+++ b/tests/qemu-iotests/134
971
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
972
973
974
size=128M
975
-IMGOPTS="encryption=on" _make_test_img $size
976
+
977
+SECRET="secret,id=sec0,data=astrochicken"
978
+SECRETALT="secret,id=sec0,data=platypus"
979
+
980
+_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" $size
981
+
982
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
983
+
984
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
985
986
echo
987
echo "== reading whole image =="
988
-echo "astrochicken" | $QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
989
+$QEMU_IO --object $SECRET -c "read 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
990
991
echo
992
echo "== rewriting whole image =="
993
-echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
994
+$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
995
996
echo
997
echo "== verify pattern =="
998
-echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
999
+$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
1000
1001
echo
1002
echo "== verify pattern failure with wrong password =="
1003
-echo "platypus" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
1004
+$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
1005
1006
1007
# success, all done
1008
diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
1009
index XXXXXXX..XXXXXXX 100644
1010
--- a/tests/qemu-iotests/134.out
1011
+++ b/tests/qemu-iotests/134.out
1012
@@ -XXX,XX +XXX,XX @@
1013
QA output created by 134
1014
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
1015
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
1016
1017
== reading whole image ==
1018
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1019
-password:
1020
read 134217728/134217728 bytes at offset 0
1021
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1022
1023
== rewriting whole image ==
1024
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1025
-password:
1026
wrote 134217728/134217728 bytes at offset 0
1027
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1028
1029
== verify pattern ==
1030
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1031
-password:
1032
read 134217728/134217728 bytes at offset 0
1033
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1034
1035
== verify pattern failure with wrong password ==
1036
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1037
-password:
1038
Pattern verification failed at offset 0, 134217728 bytes
1039
read 134217728/134217728 bytes at offset 0
1040
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1041
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
1042
index XXXXXXX..XXXXXXX 100755
1043
--- a/tests/qemu-iotests/158
1044
+++ b/tests/qemu-iotests/158
1045
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
1046
1047
size=128M
1048
TEST_IMG_BASE=$TEST_IMG.base
1049
+SECRET="secret,id=sec0,data=astrochicken"
1050
1051
TEST_IMG_SAVE=$TEST_IMG
1052
TEST_IMG=$TEST_IMG_BASE
1053
echo "== create base =="
1054
-IMGOPTS="encryption=on" _make_test_img $size
1055
+_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" $size
1056
TEST_IMG=$TEST_IMG_SAVE
1057
1058
+IMGSPECBASE="driver=$IMGFMT,file.filename=$TEST_IMG_BASE,encrypt.key-secret=sec0"
1059
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,backing.driver=$IMGFMT,backing.file.filename=$TEST_IMG_BASE,backing.encrypt.key-secret=sec0,encrypt.key-secret=sec0"
1060
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
1061
+
1062
echo
1063
echo "== writing whole image =="
1064
-echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir
1065
+$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
1066
1067
echo
1068
echo "== verify pattern =="
1069
-echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG_BASE" | _filter_qemu_io | _filter_testdir
1070
+$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
1071
1072
echo "== create overlay =="
1073
-IMGOPTS="encryption=on" _make_test_img -b "$TEST_IMG_BASE" $size
1074
+_make_test_img --object $SECRET -o "encryption=on,encrypt.key-secret=sec0" -b "$TEST_IMG_BASE" $size
1075
1076
echo
1077
echo "== writing part of a cluster =="
1078
-echo "astrochicken" | $QEMU_IO -c "write -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
1079
+$QEMU_IO --object $SECRET -c "write -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
1080
1081
echo
1082
echo "== verify pattern =="
1083
-echo "astrochicken" | $QEMU_IO -c "read -P 0xe 0 1024" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
1084
+$QEMU_IO --object $SECRET -c "read -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
1085
echo
1086
echo "== verify pattern =="
1087
-echo "astrochicken" | $QEMU_IO -c "read -P 0xa 1024 64512" "$TEST_IMG" | _filter_qemu_io | _filter_testdir
1088
+$QEMU_IO --object $SECRET -c "read -P 0xa 1024 64512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
1089
1090
1091
# success, all done
1092
diff --git a/tests/qemu-iotests/158.out b/tests/qemu-iotests/158.out
1093
index XXXXXXX..XXXXXXX 100644
1094
--- a/tests/qemu-iotests/158.out
1095
+++ b/tests/qemu-iotests/158.out
1096
@@ -XXX,XX +XXX,XX @@
1097
QA output created by 158
1098
== create base ==
1099
-Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on
1100
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
1101
1102
== writing whole image ==
1103
-Disk image 'TEST_DIR/t.qcow2.base' is encrypted.
1104
-password:
1105
wrote 134217728/134217728 bytes at offset 0
1106
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1107
1108
== verify pattern ==
1109
-Disk image 'TEST_DIR/t.qcow2.base' is encrypted.
1110
-password:
1111
read 134217728/134217728 bytes at offset 0
1112
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1113
== create overlay ==
1114
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on
1115
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base encryption=on encrypt.key-secret=sec0
1116
1117
== writing part of a cluster ==
1118
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1119
-password:
1120
wrote 1024/1024 bytes at offset 0
1121
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1122
1123
== verify pattern ==
1124
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1125
-password:
1126
read 1024/1024 bytes at offset 0
1127
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1128
1129
== verify pattern ==
1130
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
1131
-password:
1132
read 64512/64512 bytes at offset 1024
1133
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1134
*** done
1135
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
1136
index XXXXXXX..XXXXXXX 100644
1137
--- a/tests/qemu-iotests/common
1138
+++ b/tests/qemu-iotests/common
1139
@@ -XXX,XX +XXX,XX @@ export IMGPROTO=file
1140
export IMGOPTS=""
1141
export CACHEMODE="writeback"
1142
export QEMU_IO_OPTIONS=""
1143
+export QEMU_IO_OPTIONS_NO_FMT=""
1144
export CACHEMODE_IS_DEFAULT=true
1145
export QEMU_OPTIONS="-nodefaults -machine accel=qtest"
1146
export VALGRIND_QEMU=
1147
@@ -XXX,XX +XXX,XX @@ BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
1148
done
1149
1150
# Set qemu-io cache mode with $CACHEMODE we have
1151
-if [ "$IMGOPTSSYNTAX" = "true" ]; then
1152
- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
1153
-else
1154
- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
1155
+QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --cache $CACHEMODE"
1156
+
1157
+QEMU_IO_OPTIONS_NO_FMT="$QEMU_IO_OPTIONS"
1158
+if [ "$IMGOPTSSYNTAX" != "true" ]; then
1159
+ QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT"
1160
fi
1161
1162
# Set default options for qemu-img create -o if they were not specified
1163
--
86
--
1164
1.8.3.1
87
2.37.3
1165
1166
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually converting to byte-based interfaces, as they are
3
iostatus is the only field (together with .job) that needs
4
easier to reason about than sector-based. Convert another internal
4
protection using the job mutex.
5
function, preserving all existing semantics, and adding one more
6
assertion that things are still sector-aligned (so that conversions
7
to sectors in mirror_read_complete don't need to round).
8
5
9
Signed-off-by: Eric Blake <eblake@redhat.com>
6
It is set in the main loop (GLOBAL_STATE functions) but read
7
in I/O code (block_job_error_action).
8
9
In order to protect it, change block_job_iostatus_set_err
10
to block_job_iostatus_set_err_locked(), always called under
11
job lock.
12
13
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
16
Message-Id: <20220926093214.506243-17-eesposit@redhat.com>
17
[kwolf: Fixed up type of iostatus]
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
19
---
12
block/mirror.c | 74 ++++++++++++++++++++++++++--------------------------------
20
block/mirror.c | 6 +++++-
13
1 file changed, 33 insertions(+), 41 deletions(-)
21
blockjob.c | 5 +++--
22
2 files changed, 8 insertions(+), 3 deletions(-)
14
23
15
diff --git a/block/mirror.c b/block/mirror.c
24
diff --git a/block/mirror.c b/block/mirror.c
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/block/mirror.c
26
--- a/block/mirror.c
18
+++ b/block/mirror.c
27
+++ b/block/mirror.c
19
@@ -XXX,XX +XXX,XX @@ static inline int mirror_clip_sectors(MirrorBlockJob *s,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
20
/* Round offset and/or bytes to target cluster if COW is needed, and
29
BlockDriverState *bs = s->mirror_top_bs->backing->bs;
21
* return the offset of the adjusted tail against original. */
30
BlockDriverState *target_bs = blk_bs(s->target);
22
static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
31
bool need_drain = true;
23
- unsigned int *bytes)
32
+ BlockDeviceIoStatus iostatus;
24
+ uint64_t *bytes)
33
int64_t length;
34
int64_t target_length;
35
BlockDriverInfo bdi;
36
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
37
* We do so every BLKOCK_JOB_SLICE_TIME nanoseconds, or when there is
38
* an error, or when the source is clean, whichever comes first. */
39
delta = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->last_pause_ns;
40
+ WITH_JOB_LOCK_GUARD() {
41
+ iostatus = s->common.iostatus;
42
+ }
43
if (delta < BLOCK_JOB_SLICE_TIME &&
44
- s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
45
+ iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
46
if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
47
(cnt == 0 && s->in_flight > 0)) {
48
trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight);
49
diff --git a/blockjob.c b/blockjob.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/blockjob.c
52
+++ b/blockjob.c
53
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
54
return block_job_query_locked(job, errp);
55
}
56
57
-static void block_job_iostatus_set_err(BlockJob *job, int error)
58
+/* Called with job lock held */
59
+static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
25
{
60
{
26
bool need_cow;
61
if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
27
int ret = 0;
62
job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
28
@@ -XXX,XX +XXX,XX @@ static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
63
@@ -XXX,XX +XXX,XX @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
29
unsigned int align_bytes = *bytes;
64
*/
30
int max_bytes = s->granularity * s->max_iov;
65
job->job.user_paused = true;
31
66
}
32
+ assert(*bytes < INT_MAX);
67
+ block_job_iostatus_set_err_locked(job, error);
33
need_cow = !test_bit(*offset / s->granularity, s->cow_bitmap);
68
}
34
need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity,
69
- block_job_iostatus_set_err(job, error);
35
s->cow_bitmap);
70
}
36
@@ -XXX,XX +XXX,XX @@ static inline void mirror_wait_for_io(MirrorBlockJob *s)
71
return action;
37
}
72
}
38
39
/* Submit async read while handling COW.
40
- * Returns: The number of sectors copied after and including sector_num,
41
- * excluding any sectors copied prior to sector_num due to alignment.
42
- * This will be nb_sectors if no alignment is necessary, or
43
- * (new_end - sector_num) if tail is rounded up or down due to
44
+ * Returns: The number of bytes copied after and including offset,
45
+ * excluding any bytes copied prior to offset due to alignment.
46
+ * This will be @bytes if no alignment is necessary, or
47
+ * (new_end - offset) if tail is rounded up or down due to
48
* alignment or buffer limit.
49
*/
50
-static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
51
- int nb_sectors)
52
+static uint64_t mirror_do_read(MirrorBlockJob *s, int64_t offset,
53
+ uint64_t bytes)
54
{
55
BlockBackend *source = s->common.blk;
56
- int sectors_per_chunk, nb_chunks;
57
- int ret;
58
+ int nb_chunks;
59
+ uint64_t ret;
60
MirrorOp *op;
61
- int max_sectors;
62
+ uint64_t max_bytes;
63
64
- sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
65
- max_sectors = sectors_per_chunk * s->max_iov;
66
+ max_bytes = s->granularity * s->max_iov;
67
68
/* We can only handle as much as buf_size at a time. */
69
- nb_sectors = MIN(s->buf_size >> BDRV_SECTOR_BITS, nb_sectors);
70
- nb_sectors = MIN(max_sectors, nb_sectors);
71
- assert(nb_sectors);
72
- assert(nb_sectors < BDRV_REQUEST_MAX_SECTORS);
73
- ret = nb_sectors;
74
+ bytes = MIN(s->buf_size, MIN(max_bytes, bytes));
75
+ assert(bytes);
76
+ assert(bytes < BDRV_REQUEST_MAX_BYTES);
77
+ ret = bytes;
78
79
if (s->cow_bitmap) {
80
- int64_t offset = sector_num * BDRV_SECTOR_SIZE;
81
- unsigned int bytes = nb_sectors * BDRV_SECTOR_SIZE;
82
- int gap;
83
-
84
- gap = mirror_cow_align(s, &offset, &bytes);
85
- sector_num = offset / BDRV_SECTOR_SIZE;
86
- nb_sectors = bytes / BDRV_SECTOR_SIZE;
87
- ret += gap / BDRV_SECTOR_SIZE;
88
+ ret += mirror_cow_align(s, &offset, &bytes);
89
}
90
- assert(nb_sectors << BDRV_SECTOR_BITS <= s->buf_size);
91
- /* The sector range must meet granularity because:
92
+ assert(bytes <= s->buf_size);
93
+ /* The offset is granularity-aligned because:
94
* 1) Caller passes in aligned values;
95
* 2) mirror_cow_align is used only when target cluster is larger. */
96
- assert(!(sector_num % sectors_per_chunk));
97
- nb_chunks = DIV_ROUND_UP(nb_sectors, sectors_per_chunk);
98
+ assert(QEMU_IS_ALIGNED(offset, s->granularity));
99
+ /* The range is sector-aligned, since bdrv_getlength() rounds up. */
100
+ assert(QEMU_IS_ALIGNED(bytes, BDRV_SECTOR_SIZE));
101
+ nb_chunks = DIV_ROUND_UP(bytes, s->granularity);
102
103
while (s->buf_free_count < nb_chunks) {
104
- trace_mirror_yield_in_flight(s, sector_num * BDRV_SECTOR_SIZE,
105
- s->in_flight);
106
+ trace_mirror_yield_in_flight(s, offset, s->in_flight);
107
mirror_wait_for_io(s);
108
}
109
110
/* Allocate a MirrorOp that is used as an AIO callback. */
111
op = g_new(MirrorOp, 1);
112
op->s = s;
113
- op->offset = sector_num * BDRV_SECTOR_SIZE;
114
- op->bytes = nb_sectors * BDRV_SECTOR_SIZE;
115
+ op->offset = offset;
116
+ op->bytes = bytes;
117
118
/* Now make a QEMUIOVector taking enough granularity-sized chunks
119
* from s->buf_free.
120
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
121
qemu_iovec_init(&op->qiov, nb_chunks);
122
while (nb_chunks-- > 0) {
123
MirrorBuffer *buf = QSIMPLEQ_FIRST(&s->buf_free);
124
- size_t remaining = nb_sectors * BDRV_SECTOR_SIZE - op->qiov.size;
125
+ size_t remaining = bytes - op->qiov.size;
126
127
QSIMPLEQ_REMOVE_HEAD(&s->buf_free, next);
128
s->buf_free_count--;
129
@@ -XXX,XX +XXX,XX @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
130
131
/* Copy the dirty cluster. */
132
s->in_flight++;
133
- s->bytes_in_flight += nb_sectors * BDRV_SECTOR_SIZE;
134
- trace_mirror_one_iteration(s, sector_num * BDRV_SECTOR_SIZE,
135
- nb_sectors * BDRV_SECTOR_SIZE);
136
+ s->bytes_in_flight += bytes;
137
+ trace_mirror_one_iteration(s, offset, bytes);
138
139
- blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov, 0,
140
- mirror_read_complete, op);
141
+ blk_aio_preadv(source, offset, &op->qiov, 0, mirror_read_complete, op);
142
return ret;
143
}
144
145
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
146
io_sectors = mirror_clip_sectors(s, sector_num, io_sectors);
147
switch (mirror_method) {
148
case MIRROR_METHOD_COPY:
149
- io_sectors = mirror_do_read(s, sector_num, io_sectors);
150
- io_bytes_acct = io_sectors * BDRV_SECTOR_SIZE;
151
+ io_bytes_acct = mirror_do_read(s, sector_num * BDRV_SECTOR_SIZE,
152
+ io_sectors * BDRV_SECTOR_SIZE);
153
+ io_sectors = io_bytes_acct / BDRV_SECTOR_SIZE;
154
break;
155
case MIRROR_METHOD_ZERO:
156
case MIRROR_METHOD_DISCARD:
157
--
73
--
158
1.8.3.1
74
2.37.3
159
160
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Add format driver handler, which should mark loaded read-only
3
Some callbacks implementation use bdrv_* APIs that assume the
4
bitmaps as 'IN_USE' in the image and unset read_only field in
4
AioContext lock is held. Make sure this invariant is documented.
5
corresponding BdrvDirtyBitmap's.
6
5
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20220926093214.506243-18-eesposit@redhat.com>
10
Message-id: 20170628120530.31251-14-vsementsov@virtuozzo.com
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
11
---
13
block.c | 19 +++++++++++++++++++
12
include/qemu/job.h | 27 +++++++++++++++++++++++++--
14
include/block/block_int.h | 7 +++++++
13
1 file changed, 25 insertions(+), 2 deletions(-)
15
2 files changed, 26 insertions(+)
16
14
17
diff --git a/block.c b/block.c
15
diff --git a/include/qemu/job.h b/include/qemu/job.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
17
--- a/include/qemu/job.h
20
+++ b/block.c
18
+++ b/include/qemu/job.h
21
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
19
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
22
{
20
/** True if this job should automatically dismiss itself */
23
BlockDriver *drv;
21
bool auto_dismiss;
24
BlockDriverState *bs;
22
25
+ bool old_can_write, new_can_write;
23
- /** The completion function that will be called when the job completes. */
26
27
assert(reopen_state != NULL);
28
bs = reopen_state->bs;
29
drv = bs->drv;
30
assert(drv != NULL);
31
32
+ old_can_write =
33
+ !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
34
+
35
/* If there are any driver level actions to take */
36
if (drv->bdrv_reopen_commit) {
37
drv->bdrv_reopen_commit(reopen_state);
38
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
39
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
40
41
bdrv_refresh_limits(bs, NULL);
42
+
43
+ new_can_write =
44
+ !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE);
45
+ if (!old_can_write && new_can_write && drv->bdrv_reopen_bitmaps_rw) {
46
+ Error *local_err = NULL;
47
+ if (drv->bdrv_reopen_bitmaps_rw(bs, &local_err) < 0) {
48
+ /* This is not fatal, bitmaps just left read-only, so all following
49
+ * writes will fail. User can remove read-only bitmaps to unblock
50
+ * writes.
51
+ */
52
+ error_reportf_err(local_err,
53
+ "%s: Failed to make dirty bitmaps writable: ",
54
+ bdrv_get_node_name(bs));
55
+ }
56
+ }
57
}
58
59
/*
60
diff --git a/include/block/block_int.h b/include/block/block_int.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/include/block/block_int.h
63
+++ b/include/block/block_int.h
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
65
uint64_t parent_perm, uint64_t parent_shared,
66
uint64_t *nperm, uint64_t *nshared);
67
68
+ /**
24
+ /**
69
+ * Bitmaps should be marked as 'IN_USE' in the image on reopening image
25
+ * The completion function that will be called when the job completes.
70
+ * as rw. This handler should realize it. It also should unset readonly
26
+ * Called with AioContext lock held, since many callback implementations
71
+ * field of BlockDirtyBitmap's in case of success.
27
+ * use bdrv_* functions that require to hold the lock.
72
+ */
28
+ */
73
+ int (*bdrv_reopen_bitmaps_rw)(BlockDriverState *bs, Error **errp);
29
BlockCompletionFunc *cb;
74
+
30
75
QLIST_ENTRY(BlockDriver) list;
31
/** The opaque value that is passed to the completion function. */
32
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
33
*
34
* This callback will not be invoked if the job has already failed.
35
* If it fails, abort and then clean will be called.
36
+ *
37
+ * Called with AioContext lock held, since many callbacs implementations
38
+ * use bdrv_* functions that require to hold the lock.
39
*/
40
int (*prepare)(Job *job);
41
42
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
43
*
44
* All jobs will complete with a call to either .commit() or .abort() but
45
* never both.
46
+ *
47
+ * Called with AioContext lock held, since many callback implementations
48
+ * use bdrv_* functions that require to hold the lock.
49
*/
50
void (*commit)(Job *job);
51
52
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
53
*
54
* All jobs will complete with a call to either .commit() or .abort() but
55
* never both.
56
+ *
57
+ * Called with AioContext lock held, since many callback implementations
58
+ * use bdrv_* functions that require to hold the lock.
59
*/
60
void (*abort)(Job *job);
61
62
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
63
* .commit() or .abort(). Regardless of which callback is invoked after
64
* completion, .clean() will always be called, even if the job does not
65
* belong to a transaction group.
66
+ *
67
+ * Called with AioContext lock held, since many callbacs implementations
68
+ * use bdrv_* functions that require to hold the lock.
69
*/
70
void (*clean)(Job *job);
71
72
@@ -XXX,XX +XXX,XX @@ struct JobDriver {
73
* READY).
74
* (If the callback is NULL, the job is assumed to terminate
75
* without I/O.)
76
+ *
77
+ * Called with AioContext lock held, since many callback implementations
78
+ * use bdrv_* functions that require to hold the lock.
79
*/
80
bool (*cancel)(Job *job, bool force);
81
82
83
- /** Called when the job is freed */
84
+ /**
85
+ * Called when the job is freed.
86
+ * Called with AioContext lock held, since many callback implementations
87
+ * use bdrv_* functions that require to hold the lock.
88
+ */
89
void (*free)(Job *job);
76
};
90
};
77
91
78
--
92
--
79
1.8.3.1
93
2.37.3
80
81
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Change the job_{lock/unlock} and macros to use job_mutex.
4
byte-based. In the common case, allocation is unlikely to ever use
5
values that are not naturally sector-aligned, but it is possible
6
that byte-based values will let us be more precise about allocation
7
at the end of an unaligned file that can do byte-based access.
8
4
9
Changing the signature of the function to use int64_t *pnum ensures
5
Now that they are not nop anymore, remove the aiocontext
10
that the compiler enforces that all callers are updated. For now,
6
to avoid deadlocks.
11
the io.c layer still assert()s that all callers are sector-aligned,
12
but that can be relaxed when a later patch implements byte-based
13
block status. Therefore, for the most part this patch is just the
14
addition of scaling at the callers followed by inverse scaling at
15
bdrv_is_allocated(). But some code, particularly stream_run(),
16
gets a lot simpler because it no longer has to mess with sectors.
17
Leave comments where we can further simplify by switching to
18
byte-based iterations, once later patches eliminate the need for
19
sector-aligned operations.
20
7
21
For ease of review, bdrv_is_allocated() was tackled separately.
8
Therefore:
9
- when possible, remove completely the aiocontext lock/unlock pair
10
- if it is used by some other function too, reduce the locking
11
section as much as possible, leaving the job API outside.
12
- change AIO_WAIT_WHILE in AIO_WAIT_WHILE_UNLOCKED, since we
13
are not using the aiocontext lock anymore
22
14
23
Signed-off-by: Eric Blake <eblake@redhat.com>
15
The only functions that still need the aiocontext lock are:
16
- the JobDriver callbacks, already documented in job.h
17
- job_cancel_sync() in replication.c is called with aio_context_lock
18
taken, but now job is using AIO_WAIT_WHILE_UNLOCKED so we need to
19
release the lock.
20
21
Reduce the locking section to only cover the callback invocation
22
and document the functions that take the AioContext lock,
23
to avoid taking it twice.
24
25
Also remove real_job_{lock/unlock}, as they are replaced by the
26
public functions.
27
28
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
29
Message-Id: <20220926093214.506243-19-eesposit@redhat.com>
30
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
32
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
33
---
26
block/commit.c | 20 ++++++++------------
34
include/qemu/job.h | 17 ++---
27
block/io.c | 38 ++++++++++++++++++--------------------
35
block/replication.c | 2 +
28
block/mirror.c | 8 +++++++-
36
blockdev.c | 72 +++-----------------
29
block/replication.c | 17 ++++++++++++-----
37
job-qmp.c | 46 +++----------
30
block/stream.c | 23 +++++++++--------------
38
job.c | 111 +++++++++----------------------
31
include/block/block.h | 2 +-
39
qemu-img.c | 2 -
32
qemu-img.c | 13 ++++++++++---
40
tests/unit/test-bdrv-drain.c | 4 +-
33
7 files changed, 65 insertions(+), 56 deletions(-)
41
tests/unit/test-block-iothread.c | 2 +-
42
tests/unit/test-blockjob.c | 19 +++---
43
9 files changed, 72 insertions(+), 203 deletions(-)
34
44
35
diff --git a/block/commit.c b/block/commit.c
45
diff --git a/include/qemu/job.h b/include/qemu/job.h
36
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
37
--- a/block/commit.c
47
--- a/include/qemu/job.h
38
+++ b/block/commit.c
48
+++ b/include/qemu/job.h
39
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
49
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
40
int64_t offset;
50
AioContext *aio_context;
41
uint64_t delay_ns = 0;
51
42
int ret = 0;
52
43
- int n = 0; /* sectors */
53
- /** Protected by AioContext lock */
44
+ int64_t n = 0; /* bytes */
54
+ /** Protected by job_mutex */
45
void *buf = NULL;
55
46
int bytes_written = 0;
56
/** Reference count of the block job */
47
int64_t base_len;
57
int refcnt;
48
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
58
@@ -XXX,XX +XXX,XX @@ typedef struct Job {
49
59
/**
50
buf = blk_blockalign(s->top, COMMIT_BUFFER_SIZE);
60
* Set to false by the job while the coroutine has yielded and may be
51
61
* re-entered by job_enter(). There may still be I/O or event loop activity
52
- for (offset = 0; offset < s->common.len; offset += n * BDRV_SECTOR_SIZE) {
62
- * pending. Accessed under block_job_mutex (in blockjob.c).
53
+ for (offset = 0; offset < s->common.len; offset += n) {
63
+ * pending. Accessed under job_mutex.
54
bool copy;
64
*
55
65
* When the job is deferred to the main loop, busy is true as long as the
56
/* Note that even when no rate limit is applied we need to yield
66
* bottom half is still pending.
57
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
67
@@ -XXX,XX +XXX,XX @@ typedef enum JobCreateFlags {
58
}
68
59
/* Copy if allocated above the base */
69
extern QemuMutex job_mutex;
60
ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base),
70
61
- offset / BDRV_SECTOR_SIZE,
71
-#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */
62
- COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
72
+#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex)
63
- &n);
73
64
+ offset, COMMIT_BUFFER_SIZE, &n);
74
-#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */
65
copy = (ret == 1);
75
+#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex)
66
- trace_commit_one_iteration(s, offset, n * BDRV_SECTOR_SIZE, ret);
76
67
+ trace_commit_one_iteration(s, offset, n, ret);
77
/**
68
if (copy) {
78
* job_lock:
69
- ret = commit_populate(s->top, s->base, offset,
79
@@ -XXX,XX +XXX,XX @@ void job_ref_locked(Job *job);
70
- n * BDRV_SECTOR_SIZE, buf);
80
/**
71
- bytes_written += n * BDRV_SECTOR_SIZE;
81
* Release a reference that was previously acquired with job_ref() or
72
+ ret = commit_populate(s->top, s->base, offset, n, buf);
82
* job_create(). If it's the last reference to the object, it will be freed.
73
+ bytes_written += n;
83
+ *
74
}
84
+ * Takes AioContext lock internally to invoke a job->driver callback.
75
if (ret < 0) {
85
*/
76
BlockErrorAction action =
86
void job_unref(Job *job);
77
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
87
78
}
88
@@ -XXX,XX +XXX,XX @@ void job_user_cancel_locked(Job *job, bool force, Error **errp);
79
}
89
* Returns the return value from the job if the job actually completed
80
/* Publish progress */
90
* during the call, or -ECANCELED if it was canceled.
81
- s->common.offset += n * BDRV_SECTOR_SIZE;
82
+ s->common.offset += n;
83
84
if (copy && s->common.speed) {
85
- delay_ns = ratelimit_calculate_delay(&s->limit,
86
- n * BDRV_SECTOR_SIZE);
87
+ delay_ns = ratelimit_calculate_delay(&s->limit, n);
88
}
89
}
90
91
diff --git a/block/io.c b/block/io.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/block/io.c
94
+++ b/block/io.c
95
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
96
/*
97
* Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP]
98
*
91
*
99
- * Return true if the given sector is allocated in any image between
92
- * Callers must hold the AioContext lock of job->aio_context.
100
- * BASE and TOP (inclusive). BASE can be NULL to check if the given
93
+ * Called with job_lock *not* held.
101
- * sector is allocated in any image of the chain. Return false otherwise,
94
*/
102
+ * Return true if (a prefix of) the given range is allocated in any image
95
int job_cancel_sync(Job *job, bool force);
103
+ * between BASE and TOP (inclusive). BASE can be NULL to check if the given
96
104
+ * offset is allocated in any image of the chain. Return false otherwise,
97
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
105
* or negative errno on failure.
98
* function).
106
*
99
*
107
- * 'pnum' is set to the number of sectors (including and immediately following
100
* Returns the return value from the job.
108
- * the specified sector) that are known to be in the same
101
- *
109
- * allocated/unallocated state.
102
- * Callers must hold the AioContext lock of job->aio_context.
110
+ * 'pnum' is set to the number of bytes (including and immediately
103
+ * Called with job_lock *not* held.
111
+ * following the specified offset) that are known to be in the same
104
*/
112
+ * allocated/unallocated state. Note that a subsequent call starting
105
int job_complete_sync(Job *job, Error **errp);
113
+ * at 'offset + *pnum' may return the same allocation status (in other
106
114
+ * words, the result is not necessarily the maximum possible range);
107
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **job, Error **errp);
115
+ * but 'pnum' will only be 0 when end of file is reached.
108
* Returns 0 if the job is successfully completed, -ECANCELED if the job was
109
* cancelled before completing, and -errno in other error cases.
116
*
110
*
111
- * Callers must hold the AioContext lock of job->aio_context.
112
+ * Called with job_lock *not* held.
117
*/
113
*/
118
int bdrv_is_allocated_above(BlockDriverState *top,
114
int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
119
BlockDriverState *base,
115
Error **errp);
120
- int64_t sector_num,
121
- int nb_sectors, int *pnum)
122
+ int64_t offset, int64_t bytes, int64_t *pnum)
123
{
124
BlockDriverState *intermediate;
125
- int ret, n = nb_sectors;
126
+ int ret;
127
+ int64_t n = bytes;
128
129
intermediate = top;
130
while (intermediate && intermediate != base) {
131
int64_t pnum_inter;
132
int64_t size_inter;
133
- int psectors_inter;
134
135
- ret = bdrv_is_allocated(intermediate, sector_num * BDRV_SECTOR_SIZE,
136
- nb_sectors * BDRV_SECTOR_SIZE,
137
- &pnum_inter);
138
+ ret = bdrv_is_allocated(intermediate, offset, bytes, &pnum_inter);
139
if (ret < 0) {
140
return ret;
141
}
142
- assert(pnum_inter < INT_MAX * BDRV_SECTOR_SIZE);
143
- psectors_inter = pnum_inter >> BDRV_SECTOR_BITS;
144
if (ret) {
145
- *pnum = psectors_inter;
146
+ *pnum = pnum_inter;
147
return 1;
148
}
149
150
- size_inter = bdrv_nb_sectors(intermediate);
151
+ size_inter = bdrv_getlength(intermediate);
152
if (size_inter < 0) {
153
return size_inter;
154
}
155
- if (n > psectors_inter &&
156
- (intermediate == top || sector_num + psectors_inter < size_inter)) {
157
- n = psectors_inter;
158
+ if (n > pnum_inter &&
159
+ (intermediate == top || offset + pnum_inter < size_inter)) {
160
+ n = pnum_inter;
161
}
162
163
intermediate = backing_bs(intermediate);
164
diff --git a/block/mirror.c b/block/mirror.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/mirror.c
167
+++ b/block/mirror.c
168
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
169
BlockDriverState *bs = s->source;
170
BlockDriverState *target_bs = blk_bs(s->target);
171
int ret, n;
172
+ int64_t count;
173
174
end = s->bdev_length / BDRV_SECTOR_SIZE;
175
176
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
177
return 0;
178
}
179
180
- ret = bdrv_is_allocated_above(bs, base, sector_num, nb_sectors, &n);
181
+ ret = bdrv_is_allocated_above(bs, base, sector_num * BDRV_SECTOR_SIZE,
182
+ nb_sectors * BDRV_SECTOR_SIZE, &count);
183
if (ret < 0) {
184
return ret;
185
}
186
187
+ /* TODO: Relax this once bdrv_is_allocated_above and dirty
188
+ * bitmaps no longer require sector alignment. */
189
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
190
+ n = count >> BDRV_SECTOR_BITS;
191
assert(n > 0);
192
if (ret == 1) {
193
bdrv_set_dirty_bitmap(s->dirty_bitmap, sector_num, n);
194
diff --git a/block/replication.c b/block/replication.c
116
diff --git a/block/replication.c b/block/replication.c
195
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
196
--- a/block/replication.c
118
--- a/block/replication.c
197
+++ b/block/replication.c
119
+++ b/block/replication.c
198
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
120
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
199
BdrvChild *top = bs->file;
121
* disk, secondary disk in backup_job_completed().
200
BdrvChild *base = s->secondary_disk;
122
*/
201
BdrvChild *target;
123
if (s->backup_job) {
202
- int ret, n;
124
+ aio_context_release(aio_context);
203
+ int ret;
125
job_cancel_sync(&s->backup_job->job, true);
204
+ int64_t n;
126
+ aio_context_acquire(aio_context);
205
127
}
206
ret = replication_get_io_status(s);
128
207
if (ret < 0) {
129
if (!failover) {
208
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
130
diff --git a/blockdev.c b/blockdev.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/blockdev.c
133
+++ b/blockdev.c
134
@@ -XXX,XX +XXX,XX @@ void blockdev_mark_auto_del(BlockBackend *blk)
135
for (job = block_job_next_locked(NULL); job;
136
job = block_job_next_locked(job)) {
137
if (block_job_has_bdrv(job, blk_bs(blk))) {
138
- AioContext *aio_context = job->job.aio_context;
139
- aio_context_acquire(aio_context);
140
-
141
job_cancel_locked(&job->job, false);
142
-
143
- aio_context_release(aio_context);
144
}
145
}
146
147
@@ -XXX,XX +XXX,XX @@ static void drive_backup_abort(BlkActionState *common)
148
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
149
150
if (state->job) {
151
- AioContext *aio_context;
152
-
153
- aio_context = bdrv_get_aio_context(state->bs);
154
- aio_context_acquire(aio_context);
155
-
156
job_cancel_sync(&state->job->job, true);
157
-
158
- aio_context_release(aio_context);
159
}
160
}
161
162
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_abort(BlkActionState *common)
163
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
164
165
if (state->job) {
166
- AioContext *aio_context;
167
-
168
- aio_context = bdrv_get_aio_context(state->bs);
169
- aio_context_acquire(aio_context);
170
-
171
job_cancel_sync(&state->job->job, true);
172
-
173
- aio_context_release(aio_context);
174
}
175
}
176
177
@@ -XXX,XX +XXX,XX @@ out:
178
}
179
180
/*
181
- * Get a block job using its ID and acquire its AioContext.
182
- * Called with job_mutex held.
183
+ * Get a block job using its ID. Called with job_mutex held.
184
*/
185
-static BlockJob *find_block_job_locked(const char *id,
186
- AioContext **aio_context,
187
- Error **errp)
188
+static BlockJob *find_block_job_locked(const char *id, Error **errp)
189
{
190
BlockJob *job;
191
192
assert(id != NULL);
193
194
- *aio_context = NULL;
195
-
196
job = block_job_get_locked(id);
197
198
if (!job) {
199
@@ -XXX,XX +XXX,XX @@ static BlockJob *find_block_job_locked(const char *id,
200
return NULL;
201
}
202
203
- *aio_context = block_job_get_aio_context(job);
204
- aio_context_acquire(*aio_context);
205
-
206
return job;
207
}
208
209
void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp)
210
{
211
- AioContext *aio_context;
212
BlockJob *job;
213
214
JOB_LOCK_GUARD();
215
- job = find_block_job_locked(device, &aio_context, errp);
216
+ job = find_block_job_locked(device, errp);
217
218
if (!job) {
219
return;
220
}
221
222
block_job_set_speed_locked(job, speed, errp);
223
- aio_context_release(aio_context);
224
}
225
226
void qmp_block_job_cancel(const char *device,
227
bool has_force, bool force, Error **errp)
228
{
229
- AioContext *aio_context;
230
BlockJob *job;
231
232
JOB_LOCK_GUARD();
233
- job = find_block_job_locked(device, &aio_context, errp);
234
+ job = find_block_job_locked(device, errp);
235
236
if (!job) {
237
return;
238
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_cancel(const char *device,
239
if (job_user_paused_locked(&job->job) && !force) {
240
error_setg(errp, "The block job for device '%s' is currently paused",
241
device);
242
- goto out;
243
+ return;
244
}
245
246
trace_qmp_block_job_cancel(job);
247
job_user_cancel_locked(&job->job, force, errp);
248
-out:
249
- aio_context_release(aio_context);
250
}
251
252
void qmp_block_job_pause(const char *device, Error **errp)
253
{
254
- AioContext *aio_context;
255
BlockJob *job;
256
257
JOB_LOCK_GUARD();
258
- job = find_block_job_locked(device, &aio_context, errp);
259
+ job = find_block_job_locked(device, errp);
260
261
if (!job) {
262
return;
263
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_pause(const char *device, Error **errp)
264
265
trace_qmp_block_job_pause(job);
266
job_user_pause_locked(&job->job, errp);
267
- aio_context_release(aio_context);
268
}
269
270
void qmp_block_job_resume(const char *device, Error **errp)
271
{
272
- AioContext *aio_context;
273
BlockJob *job;
274
275
JOB_LOCK_GUARD();
276
- job = find_block_job_locked(device, &aio_context, errp);
277
+ job = find_block_job_locked(device, errp);
278
279
if (!job) {
280
return;
281
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_resume(const char *device, Error **errp)
282
283
trace_qmp_block_job_resume(job);
284
job_user_resume_locked(&job->job, errp);
285
- aio_context_release(aio_context);
286
}
287
288
void qmp_block_job_complete(const char *device, Error **errp)
289
{
290
- AioContext *aio_context;
291
BlockJob *job;
292
293
JOB_LOCK_GUARD();
294
- job = find_block_job_locked(device, &aio_context, errp);
295
+ job = find_block_job_locked(device, errp);
296
297
if (!job) {
298
return;
299
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_complete(const char *device, Error **errp)
300
301
trace_qmp_block_job_complete(job);
302
job_complete_locked(&job->job, errp);
303
- aio_context_release(aio_context);
304
}
305
306
void qmp_block_job_finalize(const char *id, Error **errp)
307
{
308
- AioContext *aio_context;
309
BlockJob *job;
310
311
JOB_LOCK_GUARD();
312
- job = find_block_job_locked(id, &aio_context, errp);
313
+ job = find_block_job_locked(id, errp);
314
315
if (!job) {
316
return;
317
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_finalize(const char *id, Error **errp)
318
job_ref_locked(&job->job);
319
job_finalize_locked(&job->job, errp);
320
321
- /*
322
- * Job's context might have changed via job_finalize (and job_txn_apply
323
- * automatically acquires the new one), so make sure we release the correct
324
- * one.
325
- */
326
- aio_context = block_job_get_aio_context(job);
327
job_unref_locked(&job->job);
328
- aio_context_release(aio_context);
329
}
330
331
void qmp_block_job_dismiss(const char *id, Error **errp)
332
{
333
- AioContext *aio_context;
334
BlockJob *bjob;
335
Job *job;
336
337
JOB_LOCK_GUARD();
338
- bjob = find_block_job_locked(id, &aio_context, errp);
339
+ bjob = find_block_job_locked(id, errp);
340
341
if (!bjob) {
342
return;
343
@@ -XXX,XX +XXX,XX @@ void qmp_block_job_dismiss(const char *id, Error **errp)
344
trace_qmp_block_job_dismiss(bjob);
345
job = &bjob->job;
346
job_dismiss_locked(&job, errp);
347
- aio_context_release(aio_context);
348
}
349
350
void qmp_change_backing_file(const char *device,
351
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
352
for (job = block_job_next_locked(NULL); job;
353
job = block_job_next_locked(job)) {
354
BlockJobInfo *value;
355
- AioContext *aio_context;
356
357
if (block_job_is_internal(job)) {
358
continue;
359
}
360
- aio_context = block_job_get_aio_context(job);
361
- aio_context_acquire(aio_context);
362
value = block_job_query_locked(job, errp);
363
- aio_context_release(aio_context);
364
if (!value) {
365
qapi_free_BlockJobInfoList(head);
366
return NULL;
367
diff --git a/job-qmp.c b/job-qmp.c
368
index XXXXXXX..XXXXXXX 100644
369
--- a/job-qmp.c
370
+++ b/job-qmp.c
371
@@ -XXX,XX +XXX,XX @@
372
#include "trace/trace-root.h"
373
374
/*
375
- * Get a job using its ID and acquire its AioContext.
376
- * Called with job_mutex held.
377
+ * Get a job using its ID. Called with job_mutex held.
378
*/
379
-static Job *find_job_locked(const char *id,
380
- AioContext **aio_context,
381
- Error **errp)
382
+static Job *find_job_locked(const char *id, Error **errp)
383
{
384
Job *job;
385
386
- *aio_context = NULL;
387
-
388
job = job_get_locked(id);
389
if (!job) {
390
error_setg(errp, "Job not found");
391
return NULL;
392
}
393
394
- *aio_context = job->aio_context;
395
- aio_context_acquire(*aio_context);
396
-
397
return job;
398
}
399
400
void qmp_job_cancel(const char *id, Error **errp)
401
{
402
- AioContext *aio_context;
403
Job *job;
404
405
JOB_LOCK_GUARD();
406
- job = find_job_locked(id, &aio_context, errp);
407
+ job = find_job_locked(id, errp);
408
409
if (!job) {
410
return;
411
@@ -XXX,XX +XXX,XX @@ void qmp_job_cancel(const char *id, Error **errp)
412
413
trace_qmp_job_cancel(job);
414
job_user_cancel_locked(job, true, errp);
415
- aio_context_release(aio_context);
416
}
417
418
void qmp_job_pause(const char *id, Error **errp)
419
{
420
- AioContext *aio_context;
421
Job *job;
422
423
JOB_LOCK_GUARD();
424
- job = find_job_locked(id, &aio_context, errp);
425
+ job = find_job_locked(id, errp);
426
427
if (!job) {
428
return;
429
@@ -XXX,XX +XXX,XX @@ void qmp_job_pause(const char *id, Error **errp)
430
431
trace_qmp_job_pause(job);
432
job_user_pause_locked(job, errp);
433
- aio_context_release(aio_context);
434
}
435
436
void qmp_job_resume(const char *id, Error **errp)
437
{
438
- AioContext *aio_context;
439
Job *job;
440
441
JOB_LOCK_GUARD();
442
- job = find_job_locked(id, &aio_context, errp);
443
+ job = find_job_locked(id, errp);
444
445
if (!job) {
446
return;
447
@@ -XXX,XX +XXX,XX @@ void qmp_job_resume(const char *id, Error **errp)
448
449
trace_qmp_job_resume(job);
450
job_user_resume_locked(job, errp);
451
- aio_context_release(aio_context);
452
}
453
454
void qmp_job_complete(const char *id, Error **errp)
455
{
456
- AioContext *aio_context;
457
Job *job;
458
459
JOB_LOCK_GUARD();
460
- job = find_job_locked(id, &aio_context, errp);
461
+ job = find_job_locked(id, errp);
462
463
if (!job) {
464
return;
465
@@ -XXX,XX +XXX,XX @@ void qmp_job_complete(const char *id, Error **errp)
466
467
trace_qmp_job_complete(job);
468
job_complete_locked(job, errp);
469
- aio_context_release(aio_context);
470
}
471
472
void qmp_job_finalize(const char *id, Error **errp)
473
{
474
- AioContext *aio_context;
475
Job *job;
476
477
JOB_LOCK_GUARD();
478
- job = find_job_locked(id, &aio_context, errp);
479
+ job = find_job_locked(id, errp);
480
481
if (!job) {
482
return;
483
@@ -XXX,XX +XXX,XX @@ void qmp_job_finalize(const char *id, Error **errp)
484
job_ref_locked(job);
485
job_finalize_locked(job, errp);
486
487
- /*
488
- * Job's context might have changed via job_finalize (and job_txn_apply
489
- * automatically acquires the new one), so make sure we release the correct
490
- * one.
491
- */
492
- aio_context = job->aio_context;
493
job_unref_locked(job);
494
- aio_context_release(aio_context);
495
}
496
497
void qmp_job_dismiss(const char *id, Error **errp)
498
{
499
- AioContext *aio_context;
500
Job *job;
501
502
JOB_LOCK_GUARD();
503
- job = find_job_locked(id, &aio_context, errp);
504
+ job = find_job_locked(id, errp);
505
506
if (!job) {
507
return;
508
@@ -XXX,XX +XXX,XX @@ void qmp_job_dismiss(const char *id, Error **errp)
509
510
trace_qmp_job_dismiss(job);
511
job_dismiss_locked(&job, errp);
512
- aio_context_release(aio_context);
513
}
514
515
/* Called with job_mutex held. */
516
@@ -XXX,XX +XXX,XX @@ JobInfoList *qmp_query_jobs(Error **errp)
517
518
for (job = job_next_locked(NULL); job; job = job_next_locked(job)) {
519
JobInfo *value;
520
- AioContext *aio_context;
521
522
if (job_is_internal(job)) {
523
continue;
524
}
525
- aio_context = job->aio_context;
526
- aio_context_acquire(aio_context);
527
value = job_query_single_locked(job, errp);
528
- aio_context_release(aio_context);
529
if (!value) {
530
qapi_free_JobInfoList(head);
531
return NULL;
532
diff --git a/job.c b/job.c
533
index XXXXXXX..XXXXXXX 100644
534
--- a/job.c
535
+++ b/job.c
536
@@ -XXX,XX +XXX,XX @@
537
*
538
* The second includes functions used by the job drivers and sometimes
539
* by the core block layer. These delegate the locking to the callee instead.
540
- *
541
- * TODO Actually make this true
542
*/
543
544
/*
545
@@ -XXX,XX +XXX,XX @@ struct JobTxn {
546
};
547
548
void job_lock(void)
549
-{
550
- /* nop */
551
-}
552
-
553
-void job_unlock(void)
554
-{
555
- /* nop */
556
-}
557
-
558
-static void real_job_lock(void)
559
{
560
qemu_mutex_lock(&job_mutex);
561
}
562
563
-static void real_job_unlock(void)
564
+void job_unlock(void)
565
{
566
qemu_mutex_unlock(&job_mutex);
567
}
568
@@ -XXX,XX +XXX,XX @@ static void job_txn_del_job_locked(Job *job)
569
/* Called with job_mutex held, but releases it temporarily. */
570
static int job_txn_apply_locked(Job *job, int fn(Job *))
571
{
572
- AioContext *inner_ctx;
573
Job *other_job, *next;
574
JobTxn *txn = job->txn;
575
int rc = 0;
576
@@ -XXX,XX +XXX,XX @@ static int job_txn_apply_locked(Job *job, int fn(Job *))
577
* break AIO_WAIT_WHILE from within fn.
209
*/
578
*/
210
qemu_iovec_init(&hd_qiov, qiov->niov);
579
job_ref_locked(job);
211
while (remaining_sectors > 0) {
580
- aio_context_release(job->aio_context);
212
- ret = bdrv_is_allocated_above(top->bs, base->bs, sector_num,
581
213
- remaining_sectors, &n);
582
QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) {
214
+ int64_t count;
583
- inner_ctx = other_job->aio_context;
584
- aio_context_acquire(inner_ctx);
585
rc = fn(other_job);
586
- aio_context_release(inner_ctx);
587
if (rc) {
588
break;
589
}
590
}
591
592
- /*
593
- * Note that job->aio_context might have been changed by calling fn, so we
594
- * can't use a local variable to cache it.
595
- */
596
- aio_context_acquire(job->aio_context);
597
job_unref_locked(job);
598
return rc;
599
}
600
@@ -XXX,XX +XXX,XX @@ void job_unref_locked(Job *job)
601
assert(!job->txn);
602
603
if (job->driver->free) {
604
+ AioContext *aio_context = job->aio_context;
605
job_unlock();
606
+ /* FIXME: aiocontext lock is required because cb calls blk_unref */
607
+ aio_context_acquire(aio_context);
608
job->driver->free(job);
609
+ aio_context_release(aio_context);
610
job_lock();
611
}
612
613
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
614
return;
615
}
616
617
- real_job_lock();
618
if (job->busy) {
619
- real_job_unlock();
620
return;
621
}
622
623
if (fn && !fn(job)) {
624
- real_job_unlock();
625
return;
626
}
627
628
assert(!job->deferred_to_main_loop);
629
timer_del(&job->sleep_timer);
630
job->busy = true;
631
- real_job_unlock();
632
job_unlock();
633
aio_co_wake(job->co);
634
job_lock();
635
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
636
{
637
AioContext *next_aio_context;
638
639
- real_job_lock();
640
if (ns != -1) {
641
timer_mod(&job->sleep_timer, ns);
642
}
643
job->busy = false;
644
job_event_idle_locked(job);
645
- real_job_unlock();
646
job_unlock();
647
qemu_coroutine_yield();
648
job_lock();
649
@@ -XXX,XX +XXX,XX @@ static void job_clean(Job *job)
650
}
651
}
652
653
-/* Called with job_mutex held, but releases it temporarily */
654
+/*
655
+ * Called with job_mutex held, but releases it temporarily.
656
+ * Takes AioContext lock internally to invoke a job->driver callback.
657
+ */
658
static int job_finalize_single_locked(Job *job)
659
{
660
int job_ret;
661
+ AioContext *ctx = job->aio_context;
662
663
assert(job_is_completed_locked(job));
664
665
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
666
667
job_ret = job->ret;
668
job_unlock();
669
+ aio_context_acquire(ctx);
670
671
if (!job_ret) {
672
job_commit(job);
673
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
674
}
675
job_clean(job);
676
677
- job_lock();
678
-
679
if (job->cb) {
680
- job_ret = job->ret;
681
- job_unlock();
682
job->cb(job->opaque, job_ret);
683
- job_lock();
684
}
685
686
+ aio_context_release(ctx);
687
+ job_lock();
215
+
688
+
216
+ ret = bdrv_is_allocated_above(top->bs, base->bs,
689
/* Emit events only if we actually started */
217
+ sector_num * BDRV_SECTOR_SIZE,
690
if (job_started_locked(job)) {
218
+ remaining_sectors * BDRV_SECTOR_SIZE,
691
if (job_is_cancelled_locked(job)) {
219
+ &count);
692
@@ -XXX,XX +XXX,XX @@ static int job_finalize_single_locked(Job *job)
220
if (ret < 0) {
693
return 0;
221
goto out1;
694
}
695
696
-/* Called with job_mutex held, but releases it temporarily */
697
+/*
698
+ * Called with job_mutex held, but releases it temporarily.
699
+ * Takes AioContext lock internally to invoke a job->driver callback.
700
+ */
701
static void job_cancel_async_locked(Job *job, bool force)
702
{
703
+ AioContext *ctx = job->aio_context;
704
GLOBAL_STATE_CODE();
705
if (job->driver->cancel) {
706
job_unlock();
707
+ aio_context_acquire(ctx);
708
force = job->driver->cancel(job, force);
709
+ aio_context_release(ctx);
710
job_lock();
711
} else {
712
/* No .cancel() means the job will behave as if force-cancelled */
713
@@ -XXX,XX +XXX,XX @@ static void job_cancel_async_locked(Job *job, bool force)
714
}
715
}
716
717
-/* Called with job_mutex held, but releases it temporarily. */
718
+/*
719
+ * Called with job_mutex held, but releases it temporarily.
720
+ * Takes AioContext lock internally to invoke a job->driver callback.
721
+ */
722
static void job_completed_txn_abort_locked(Job *job)
723
{
724
- AioContext *ctx;
725
JobTxn *txn = job->txn;
726
Job *other_job;
727
728
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort_locked(Job *job)
729
txn->aborting = true;
730
job_txn_ref_locked(txn);
731
732
- /*
733
- * We can only hold the single job's AioContext lock while calling
734
- * job_finalize_single() because the finalization callbacks can involve
735
- * calls of AIO_WAIT_WHILE(), which could deadlock otherwise.
736
- * Note that the job's AioContext may change when it is finalized.
737
- */
738
job_ref_locked(job);
739
- aio_context_release(job->aio_context);
740
741
/* Other jobs are effectively cancelled by us, set the status for
742
* them; this job, however, may or may not be cancelled, depending
743
* on the caller, so leave it. */
744
QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
745
if (other_job != job) {
746
- ctx = other_job->aio_context;
747
- aio_context_acquire(ctx);
748
/*
749
* This is a transaction: If one job failed, no result will matter.
750
* Therefore, pass force=true to terminate all other jobs as quickly
751
* as possible.
752
*/
753
job_cancel_async_locked(other_job, true);
754
- aio_context_release(ctx);
222
}
755
}
223
756
}
224
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
757
while (!QLIST_EMPTY(&txn->jobs)) {
225
+ n = count >> BDRV_SECTOR_BITS;
758
other_job = QLIST_FIRST(&txn->jobs);
226
qemu_iovec_reset(&hd_qiov);
759
- /*
227
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, n * BDRV_SECTOR_SIZE);
760
- * The job's AioContext may change, so store it in @ctx so we
228
+ qemu_iovec_concat(&hd_qiov, qiov, bytes_done, count);
761
- * release the same context that we have acquired before.
229
762
- */
230
target = ret ? top : base;
763
- ctx = other_job->aio_context;
231
ret = bdrv_co_writev(target, sector_num, n, &hd_qiov);
764
- aio_context_acquire(ctx);
232
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
765
if (!job_is_completed_locked(other_job)) {
233
766
assert(job_cancel_requested_locked(other_job));
234
remaining_sectors -= n;
767
job_finish_sync_locked(other_job, NULL, NULL);
235
sector_num += n;
236
- bytes_done += n * BDRV_SECTOR_SIZE;
237
+ bytes_done += count;
238
}
239
240
out1:
241
diff --git a/block/stream.c b/block/stream.c
242
index XXXXXXX..XXXXXXX 100644
243
--- a/block/stream.c
244
+++ b/block/stream.c
245
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
246
uint64_t delay_ns = 0;
247
int error = 0;
248
int ret = 0;
249
- int n = 0; /* sectors */
250
+ int64_t n = 0; /* bytes */
251
void *buf;
252
253
if (!bs->backing) {
254
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
255
bdrv_enable_copy_on_read(bs);
256
}
257
258
- for ( ; offset < s->common.len; offset += n * BDRV_SECTOR_SIZE) {
259
+ for ( ; offset < s->common.len; offset += n) {
260
bool copy;
261
- int64_t count = 0;
262
263
/* Note that even when no rate limit is applied we need to yield
264
* with no pending I/O here so that bdrv_drain_all() returns.
265
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
266
267
copy = false;
268
269
- ret = bdrv_is_allocated(bs, offset, STREAM_BUFFER_SIZE, &count);
270
- /* TODO relax this once bdrv_is_allocated does not enforce sectors */
271
- assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
272
- n = count >> BDRV_SECTOR_BITS;
273
+ ret = bdrv_is_allocated(bs, offset, STREAM_BUFFER_SIZE, &n);
274
if (ret == 1) {
275
/* Allocated in the top, no need to copy. */
276
} else if (ret >= 0) {
277
/* Copy if allocated in the intermediate images. Limit to the
278
* known-unallocated area [offset, offset+n*BDRV_SECTOR_SIZE). */
279
ret = bdrv_is_allocated_above(backing_bs(bs), base,
280
- offset / BDRV_SECTOR_SIZE, n, &n);
281
+ offset, n, &n);
282
283
/* Finish early if end of backing file has been reached */
284
if (ret == 0 && n == 0) {
285
- n = (s->common.len - offset) / BDRV_SECTOR_SIZE;
286
+ n = s->common.len - offset;
287
}
288
289
copy = (ret == 1);
290
}
768
}
291
- trace_stream_one_iteration(s, offset, n * BDRV_SECTOR_SIZE, ret);
769
job_finalize_single_locked(other_job);
292
+ trace_stream_one_iteration(s, offset, n, ret);
770
- aio_context_release(ctx);
293
if (copy) {
771
}
294
- ret = stream_populate(blk, offset, n * BDRV_SECTOR_SIZE, buf);
772
295
+ ret = stream_populate(blk, offset, n, buf);
773
- /*
296
}
774
- * Use job_ref()/job_unref() so we can read the AioContext here
297
if (ret < 0) {
775
- * even if the job went away during job_finalize_single().
298
BlockErrorAction action =
776
- */
299
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
777
- aio_context_acquire(job->aio_context);
300
ret = 0;
778
job_unref_locked(job);
301
779
-
302
/* Publish progress */
780
job_txn_unref_locked(txn);
303
- s->common.offset += n * BDRV_SECTOR_SIZE;
781
}
304
+ s->common.offset += n;
782
305
if (copy && s->common.speed) {
783
@@ -XXX,XX +XXX,XX @@ static void job_completed_txn_abort_locked(Job *job)
306
- delay_ns = ratelimit_calculate_delay(&s->limit,
784
static int job_prepare_locked(Job *job)
307
- n * BDRV_SECTOR_SIZE);
785
{
308
+ delay_ns = ratelimit_calculate_delay(&s->limit, n);
786
int ret;
309
}
787
+ AioContext *ctx = job->aio_context;
310
}
788
311
789
GLOBAL_STATE_CODE();
312
diff --git a/include/block/block.h b/include/block/block.h
790
+
313
index XXXXXXX..XXXXXXX 100644
791
if (job->ret == 0 && job->driver->prepare) {
314
--- a/include/block/block.h
792
job_unlock();
315
+++ b/include/block/block.h
793
+ aio_context_acquire(ctx);
316
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_block_status_above(BlockDriverState *bs,
794
ret = job->driver->prepare(job);
317
int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
795
+ aio_context_release(ctx);
318
int64_t *pnum);
796
job_lock();
319
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
797
job->ret = ret;
320
- int64_t sector_num, int nb_sectors, int *pnum);
798
job_update_rc_locked(job);
321
+ int64_t offset, int64_t bytes, int64_t *pnum);
799
}
322
800
+
323
bool bdrv_is_read_only(BlockDriverState *bs);
801
return job->ret;
324
bool bdrv_is_writable(BlockDriverState *bs);
802
}
803
804
@@ -XXX,XX +XXX,XX @@ static void job_completed_locked(Job *job)
805
static void job_exit(void *opaque)
806
{
807
Job *job = (Job *)opaque;
808
- AioContext *ctx;
809
JOB_LOCK_GUARD();
810
-
811
job_ref_locked(job);
812
- aio_context_acquire(job->aio_context);
813
814
/* This is a lie, we're not quiescent, but still doing the completion
815
* callbacks. However, completion callbacks tend to involve operations that
816
@@ -XXX,XX +XXX,XX @@ static void job_exit(void *opaque)
817
job_event_idle_locked(job);
818
819
job_completed_locked(job);
820
-
821
- /*
822
- * Note that calling job_completed can move the job to a different
823
- * aio_context, so we cannot cache from above. job_txn_apply takes care of
824
- * acquiring the new lock, and we ref/unref to avoid job_completed freeing
825
- * the job underneath us.
826
- */
827
- ctx = job->aio_context;
828
job_unref_locked(job);
829
- aio_context_release(ctx);
830
}
831
832
/**
833
@@ -XXX,XX +XXX,XX @@ int job_cancel_sync(Job *job, bool force)
834
void job_cancel_sync_all(void)
835
{
836
Job *job;
837
- AioContext *aio_context;
838
JOB_LOCK_GUARD();
839
840
while ((job = job_next_locked(NULL))) {
841
- aio_context = job->aio_context;
842
- aio_context_acquire(aio_context);
843
job_cancel_sync_locked(job, true);
844
- aio_context_release(aio_context);
845
}
846
}
847
848
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
849
}
850
851
job_unlock();
852
- AIO_WAIT_WHILE(job->aio_context,
853
- (job_enter(job), !job_is_completed(job)));
854
+ AIO_WAIT_WHILE_UNLOCKED(job->aio_context,
855
+ (job_enter(job), !job_is_completed(job)));
856
job_lock();
857
858
ret = (job_is_cancelled_locked(job) && job->ret == 0)
325
diff --git a/qemu-img.c b/qemu-img.c
859
diff --git a/qemu-img.c b/qemu-img.c
326
index XXXXXXX..XXXXXXX 100644
860
index XXXXXXX..XXXXXXX 100644
327
--- a/qemu-img.c
861
--- a/qemu-img.c
328
+++ b/qemu-img.c
862
+++ b/qemu-img.c
329
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
863
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
330
}
864
AioContext *aio_context = block_job_get_aio_context(job);
331
865
int ret = 0;
332
for (;;) {
866
333
+ int64_t count;
867
- aio_context_acquire(aio_context);
868
job_lock();
869
job_ref_locked(&job->job);
870
do {
871
@@ -XXX,XX +XXX,XX @@ static void run_block_job(BlockJob *job, Error **errp)
872
}
873
job_unref_locked(&job->job);
874
job_unlock();
875
- aio_context_release(aio_context);
876
877
/* publish completion progress only when success */
878
if (!ret) {
879
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
880
index XXXXXXX..XXXXXXX 100644
881
--- a/tests/unit/test-bdrv-drain.c
882
+++ b/tests/unit/test-bdrv-drain.c
883
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
884
tjob->prepare_ret = -EIO;
885
break;
886
}
887
+ aio_context_release(ctx);
888
889
job_start(&job->job);
890
- aio_context_release(ctx);
891
892
if (use_iothread) {
893
/* job_co_entry() is run in the I/O thread, wait for the actual job
894
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
895
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
896
}
897
898
- aio_context_acquire(ctx);
899
WITH_JOB_LOCK_GUARD() {
900
ret = job_complete_sync_locked(&job->job, &error_abort);
901
}
902
g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO));
903
904
+ aio_context_acquire(ctx);
905
if (use_iothread) {
906
blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort);
907
assert(blk_get_aio_context(blk_target) == qemu_get_aio_context());
908
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
909
index XXXXXXX..XXXXXXX 100644
910
--- a/tests/unit/test-block-iothread.c
911
+++ b/tests/unit/test-block-iothread.c
912
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
913
aio_poll(qemu_get_aio_context(), false);
914
}
915
916
- aio_context_acquire(ctx);
917
WITH_JOB_LOCK_GUARD() {
918
job_complete_sync_locked(&tjob->common.job, &error_abort);
919
}
920
+ aio_context_acquire(ctx);
921
blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
922
aio_context_release(ctx);
923
924
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
925
index XXXXXXX..XXXXXXX 100644
926
--- a/tests/unit/test-blockjob.c
927
+++ b/tests/unit/test-blockjob.c
928
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
929
BlockJob *job = &s->common;
930
BlockBackend *blk = s->blk;
931
JobStatus sts = job->job.status;
932
- AioContext *ctx;
933
-
934
- ctx = job->job.aio_context;
935
- aio_context_acquire(ctx);
936
+ AioContext *ctx = job->job.aio_context;
937
938
job_cancel_sync(&job->job, true);
939
WITH_JOB_LOCK_GUARD() {
940
@@ -XXX,XX +XXX,XX @@ static void cancel_common(CancelJob *s)
941
assert(job->job.status == JOB_STATUS_NULL);
942
job_unref_locked(&job->job);
943
}
944
- destroy_blk(blk);
945
946
+ aio_context_acquire(ctx);
947
+ destroy_blk(blk);
948
aio_context_release(ctx);
334
+
949
+
335
nb_sectors = sectors_to_process(total_sectors_over, sector_num);
950
}
336
if (nb_sectors <= 0) {
951
337
break;
952
static void test_cancel_created(void)
338
}
953
@@ -XXX,XX +XXX,XX @@ static void test_cancel_concluded(void)
339
- ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL, sector_num,
954
aio_poll(qemu_get_aio_context(), true);
340
- nb_sectors, &pnum);
955
assert_job_status_is(job, JOB_STATUS_PENDING);
341
+ ret = bdrv_is_allocated_above(blk_bs(blk_over), NULL,
956
342
+ sector_num * BDRV_SECTOR_SIZE,
957
- aio_context_acquire(job->aio_context);
343
+ nb_sectors * BDRV_SECTOR_SIZE,
958
WITH_JOB_LOCK_GUARD() {
344
+ &count);
959
job_finalize_locked(job, &error_abort);
345
if (ret < 0) {
960
+ assert(job->status == JOB_STATUS_CONCLUDED);
346
ret = 3;
961
}
347
error_report("Sector allocation test failed for %s",
962
- aio_context_release(job->aio_context);
348
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
963
- assert_job_status_is(job, JOB_STATUS_CONCLUDED);
349
goto out;
964
350
965
cancel_common(s);
351
}
966
}
352
- nb_sectors = pnum;
967
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
353
+ /* TODO relax this once bdrv_is_allocated_above does not enforce
968
354
+ * sector alignment */
969
/* Wait for the job to become READY */
355
+ assert(QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE));
970
job_start(job);
356
+ nb_sectors = count >> BDRV_SECTOR_BITS;
971
- aio_context_acquire(ctx);
357
if (ret) {
972
/*
358
ret = check_empty_sectors(blk_over, sector_num, nb_sectors,
973
* Here we are waiting for the status to change, so don't bother
359
filename_over, buf1, quiet);
974
* protecting the read every time.
975
*/
976
- AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY);
977
- aio_context_release(ctx);
978
+ AIO_WAIT_WHILE_UNLOCKED(ctx, job->status != JOB_STATUS_READY);
979
980
/* Begin the drained section, pausing the job */
981
bdrv_drain_all_begin();
982
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
983
aio_context_acquire(ctx);
984
/* This will schedule the job to resume it */
985
bdrv_drain_all_end();
986
+ aio_context_release(ctx);
987
988
WITH_JOB_LOCK_GUARD() {
989
/* But the job cannot run, so it will remain on standby */
990
@@ -XXX,XX +XXX,XX @@ static void test_complete_in_standby(void)
991
job_dismiss_locked(&job, &error_abort);
992
}
993
994
+ aio_context_acquire(ctx);
995
destroy_blk(blk);
996
aio_context_release(ctx);
997
iothread_join(iothread);
360
--
998
--
361
1.8.3.1
999
2.37.3
362
363
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
According to specification:
3
Not sure what the atomic here was supposed to do, since job.busy
4
"'MSWIN4.1' is the recommanded setting, because it is the setting least likely
4
is protected by the job lock. Since the whole function
5
to cause compatibility problems. If you want to put something else in here,
5
is called under job_mutex, just remove the atomic.
6
that is your option, but the result may be that some FAT drivers might not
7
recognize the volume."
8
6
9
Specification: "FAT: General overview of on-disk format" v1.03, page 9
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Message-Id: <20220926093214.506243-20-eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
13
---
14
block/vvfat.c | 2 +-
14
blockjob.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
16
17
diff --git a/block/vvfat.c b/block/vvfat.c
17
diff --git a/blockjob.c b/blockjob.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/vvfat.c
19
--- a/blockjob.c
20
+++ b/block/vvfat.c
20
+++ b/blockjob.c
21
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
21
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
22
bootsector->jump[0]=0xeb;
22
info = g_new0(BlockJobInfo, 1);
23
bootsector->jump[1]=0x3e;
23
info->type = g_strdup(job_type_str(&job->job));
24
bootsector->jump[2]=0x90;
24
info->device = g_strdup(job->job.id);
25
- memcpy(bootsector->name,"QEMU ",8);
25
- info->busy = qatomic_read(&job->job.busy);
26
+ memcpy(bootsector->name, "MSWIN4.1", 8);
26
+ info->busy = job->job.busy;
27
bootsector->sector_size=cpu_to_le16(0x200);
27
info->paused = job->job.pause_count > 0;
28
bootsector->sectors_per_cluster=s->sectors_per_cluster;
28
info->offset = progress_current;
29
bootsector->reserved_sectors=cpu_to_le16(1);
29
info->len = progress_total;
30
--
30
--
31
1.8.3.1
31
2.37.3
32
33
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Store persistent dirty bitmaps in qcow2 image.
3
These public functions are not used anywhere, thus can be dropped.
4
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-id: 20170628120530.31251-20-vsementsov@virtuozzo.com
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
Message-Id: <20220926093214.506243-21-eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
block/qcow2-bitmap.c | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++
12
include/block/blockjob.h | 31 ++++++++++++-------------------
11
block/qcow2.c | 9 +
13
blockjob.c | 16 ++--------------
12
block/qcow2.h | 1 +
14
2 files changed, 14 insertions(+), 33 deletions(-)
13
3 files changed, 485 insertions(+)
14
15
15
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
16
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2-bitmap.c
18
--- a/include/block/blockjob.h
18
+++ b/block/qcow2-bitmap.c
19
+++ b/include/block/blockjob.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
20
21
*/
21
#include "qemu/osdep.h"
22
22
#include "qapi/error.h"
23
/**
23
+#include "qemu/cutils.h"
24
- * block_job_next:
24
25
+ * block_job_next_locked:
25
#include "block/block_int.h"
26
* @job: A block job, or %NULL.
26
#include "block/qcow2.h"
27
*
27
@@ -XXX,XX +XXX,XX @@
28
* Get the next element from the list of block jobs after @job, or the
28
#define BME_MIN_GRANULARITY_BITS 9
29
* first one if @job is %NULL.
29
#define BME_MAX_NAME_SIZE 1023
30
*
30
31
* Returns the requested job, or %NULL if there are no more jobs left.
31
+#if BME_MAX_TABLE_SIZE * 8ULL > INT_MAX
32
+ * Called with job lock held.
32
+#error In the code bitmap table physical size assumed to fit into int
33
*/
33
+#endif
34
-BlockJob *block_job_next(BlockJob *job);
34
+
35
-
35
/* Bitmap directory entry flags */
36
-/* Same as block_job_next(), but called with job lock held. */
36
#define BME_RESERVED_FLAGS 0xfffffffcU
37
BlockJob *block_job_next_locked(BlockJob *job);
37
#define BME_FLAG_IN_USE (1U << 0)
38
38
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2BitmapTable {
39
/**
39
uint32_t size; /* number of 64bit entries */
40
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next_locked(BlockJob *job);
40
QSIMPLEQ_ENTRY(Qcow2BitmapTable) entry;
41
* Get the block job identified by @id (which must not be %NULL).
41
} Qcow2BitmapTable;
42
*
42
+typedef QSIMPLEQ_HEAD(Qcow2BitmapTableList, Qcow2BitmapTable)
43
* Returns the requested job, or %NULL if it doesn't exist.
43
+ Qcow2BitmapTableList;
44
+ * Called with job lock *not* held.
44
45
*/
45
typedef struct Qcow2Bitmap {
46
BlockJob *block_job_get(const char *id);
46
Qcow2BitmapTable table;
47
47
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2Bitmap {
48
@@ -XXX,XX +XXX,XX @@ void block_job_remove_all_bdrv(BlockJob *job);
48
uint8_t granularity_bits;
49
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs);
49
char *name;
50
50
51
/**
51
+ BdrvDirtyBitmap *dirty_bitmap;
52
- * block_job_set_speed:
52
+
53
+ * block_job_set_speed_locked:
53
QSIMPLEQ_ENTRY(Qcow2Bitmap) entry;
54
* @job: The job to set the speed for.
54
} Qcow2Bitmap;
55
* @speed: The new value
55
typedef QSIMPLEQ_HEAD(Qcow2BitmapList, Qcow2Bitmap) Qcow2BitmapList;
56
* @errp: Error object.
56
@@ -XXX,XX +XXX,XX @@ static int update_header_sync(BlockDriverState *bs)
57
*
57
return bdrv_flush(bs);
58
* Set a rate-limiting parameter for the job; the actual meaning may
59
* vary depending on the job type.
60
- */
61
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp);
62
-
63
-/*
64
- * Same as block_job_set_speed(), but called with job lock held.
65
- * Might release the lock temporarily.
66
+ *
67
+ * Called with job lock held, but might release it temporarily.
68
*/
69
bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp);
70
71
/**
72
- * block_job_query:
73
+ * block_job_query_locked:
74
* @job: The job to get information about.
75
*
76
* Return information about a job.
77
+ *
78
+ * Called with job lock held.
79
*/
80
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
81
-
82
-/* Same as block_job_query(), but called with job lock held. */
83
BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp);
84
85
/**
86
- * block_job_iostatus_reset:
87
+ * block_job_iostatus_reset_locked:
88
* @job: The job whose I/O status should be reset.
89
*
90
* Reset I/O status on @job and on BlockDriverState objects it uses,
91
* other than job->blk.
92
+ *
93
+ * Called with job lock held.
94
*/
95
-void block_job_iostatus_reset(BlockJob *job);
96
-
97
-/* Same as block_job_iostatus_reset(), but called with job lock held. */
98
void block_job_iostatus_reset_locked(BlockJob *job);
99
100
/*
101
diff --git a/blockjob.c b/blockjob.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/blockjob.c
104
+++ b/blockjob.c
105
@@ -XXX,XX +XXX,XX @@ BlockJob *block_job_next_locked(BlockJob *bjob)
106
return job ? container_of(job, BlockJob, job) : NULL;
58
}
107
}
59
108
60
+static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
109
-BlockJob *block_job_next(BlockJob *bjob)
61
+{
110
-{
62
+ size_t i;
111
- JOB_LOCK_GUARD();
63
+
112
- return block_job_next_locked(bjob);
64
+ for (i = 0; i < size; ++i) {
113
-}
65
+ cpu_to_be64s(&bitmap_table[i]);
114
-
66
+ }
115
BlockJob *block_job_get_locked(const char *id)
67
+}
68
+
69
static int check_table_entry(uint64_t entry, int cluster_size)
70
{
116
{
71
uint64_t offset;
117
Job *job = job_get_locked(id);
72
@@ -XXX,XX +XXX,XX @@ static int check_table_entry(uint64_t entry, int cluster_size)
118
@@ -XXX,XX +XXX,XX @@ bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp)
73
return 0;
119
return true;
74
}
120
}
75
121
76
+static int check_constraints_on_bitmap(BlockDriverState *bs,
122
-bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
77
+ const char *name,
123
+static bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
78
+ uint32_t granularity,
79
+ Error **errp)
80
+{
81
+ BDRVQcow2State *s = bs->opaque;
82
+ int granularity_bits = ctz32(granularity);
83
+ int64_t len = bdrv_getlength(bs);
84
+
85
+ assert(granularity > 0);
86
+ assert((granularity & (granularity - 1)) == 0);
87
+
88
+ if (len < 0) {
89
+ error_setg_errno(errp, -len, "Failed to get size of '%s'",
90
+ bdrv_get_device_or_node_name(bs));
91
+ return len;
92
+ }
93
+
94
+ if (granularity_bits > BME_MAX_GRANULARITY_BITS) {
95
+ error_setg(errp, "Granularity exceeds maximum (%llu bytes)",
96
+ 1ULL << BME_MAX_GRANULARITY_BITS);
97
+ return -EINVAL;
98
+ }
99
+ if (granularity_bits < BME_MIN_GRANULARITY_BITS) {
100
+ error_setg(errp, "Granularity is under minimum (%llu bytes)",
101
+ 1ULL << BME_MIN_GRANULARITY_BITS);
102
+ return -EINVAL;
103
+ }
104
+
105
+ if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) ||
106
+ (len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size <<
107
+ granularity_bits))
108
+ {
109
+ error_setg(errp, "Too much space will be occupied by the bitmap. "
110
+ "Use larger granularity");
111
+ return -EINVAL;
112
+ }
113
+
114
+ if (strlen(name) > BME_MAX_NAME_SIZE) {
115
+ error_setg(errp, "Name length exceeds maximum (%u characters)",
116
+ BME_MAX_NAME_SIZE);
117
+ return -EINVAL;
118
+ }
119
+
120
+ return 0;
121
+}
122
+
123
+static void clear_bitmap_table(BlockDriverState *bs, uint64_t *bitmap_table,
124
+ uint32_t bitmap_table_size)
125
+{
126
+ BDRVQcow2State *s = bs->opaque;
127
+ int i;
128
+
129
+ for (i = 0; i < bitmap_table_size; ++i) {
130
+ uint64_t addr = bitmap_table[i] & BME_TABLE_ENTRY_OFFSET_MASK;
131
+ if (!addr) {
132
+ continue;
133
+ }
134
+
135
+ qcow2_free_clusters(bs, addr, s->cluster_size, QCOW2_DISCARD_OTHER);
136
+ bitmap_table[i] = 0;
137
+ }
138
+}
139
+
140
static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
141
uint64_t **bitmap_table)
142
{
124
{
143
@@ -XXX,XX +XXX,XX @@ fail:
125
JOB_LOCK_GUARD();
144
return ret;
126
return block_job_set_speed_locked(job, speed, errp);
127
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp)
128
return info;
145
}
129
}
146
130
147
+static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb)
131
-BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
148
+{
132
-{
149
+ int ret;
133
- JOB_LOCK_GUARD();
150
+ uint64_t *bitmap_table;
134
- return block_job_query_locked(job, errp);
151
+
135
-}
152
+ ret = bitmap_table_load(bs, tb, &bitmap_table);
136
-
153
+ if (ret < 0) {
137
/* Called with job lock held */
154
+ assert(bitmap_table == NULL);
138
static void block_job_iostatus_set_err_locked(BlockJob *job, int error)
155
+ return ret;
139
{
156
+ }
140
@@ -XXX,XX +XXX,XX @@ void block_job_iostatus_reset_locked(BlockJob *job)
157
+
141
job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
158
+ clear_bitmap_table(bs, bitmap_table, tb->size);
159
+ qcow2_free_clusters(bs, tb->offset, tb->size * sizeof(uint64_t),
160
+ QCOW2_DISCARD_OTHER);
161
+ g_free(bitmap_table);
162
+
163
+ tb->offset = 0;
164
+ tb->size = 0;
165
+
166
+ return 0;
167
+}
168
+
169
/* This function returns the number of disk sectors covered by a single qcow2
170
* cluster of bitmap data. */
171
static uint64_t sectors_covered_by_bitmap_cluster(const BDRVQcow2State *s,
172
@@ -XXX,XX +XXX,XX @@ static int update_ext_header_and_dir_in_place(BlockDriverState *bs,
173
*/
174
}
142
}
175
143
176
+static int update_ext_header_and_dir(BlockDriverState *bs,
144
-void block_job_iostatus_reset(BlockJob *job)
177
+ Qcow2BitmapList *bm_list)
145
+static void block_job_iostatus_reset(BlockJob *job)
178
+{
179
+ BDRVQcow2State *s = bs->opaque;
180
+ int ret;
181
+ uint64_t new_offset = 0;
182
+ uint64_t new_size = 0;
183
+ uint32_t new_nb_bitmaps = 0;
184
+ uint64_t old_offset = s->bitmap_directory_offset;
185
+ uint64_t old_size = s->bitmap_directory_size;
186
+ uint32_t old_nb_bitmaps = s->nb_bitmaps;
187
+ uint64_t old_autocl = s->autoclear_features;
188
+
189
+ if (bm_list != NULL && !QSIMPLEQ_EMPTY(bm_list)) {
190
+ new_nb_bitmaps = bitmap_list_count(bm_list);
191
+
192
+ if (new_nb_bitmaps > QCOW2_MAX_BITMAPS) {
193
+ return -EINVAL;
194
+ }
195
+
196
+ ret = bitmap_list_store(bs, bm_list, &new_offset, &new_size, false);
197
+ if (ret < 0) {
198
+ return ret;
199
+ }
200
+
201
+ ret = bdrv_flush(bs->file->bs);
202
+ if (ret < 0) {
203
+ goto fail;
204
+ }
205
+
206
+ s->autoclear_features |= QCOW2_AUTOCLEAR_BITMAPS;
207
+ } else {
208
+ s->autoclear_features &= ~(uint64_t)QCOW2_AUTOCLEAR_BITMAPS;
209
+ }
210
+
211
+ s->bitmap_directory_offset = new_offset;
212
+ s->bitmap_directory_size = new_size;
213
+ s->nb_bitmaps = new_nb_bitmaps;
214
+
215
+ ret = update_header_sync(bs);
216
+ if (ret < 0) {
217
+ goto fail;
218
+ }
219
+
220
+ if (old_size > 0) {
221
+ qcow2_free_clusters(bs, old_offset, old_size, QCOW2_DISCARD_OTHER);
222
+ }
223
+
224
+ return 0;
225
+
226
+fail:
227
+ if (new_offset > 0) {
228
+ qcow2_free_clusters(bs, new_offset, new_size, QCOW2_DISCARD_OTHER);
229
+ }
230
+
231
+ s->bitmap_directory_offset = old_offset;
232
+ s->bitmap_directory_size = old_size;
233
+ s->nb_bitmaps = old_nb_bitmaps;
234
+ s->autoclear_features = old_autocl;
235
+
236
+ return ret;
237
+}
238
+
239
/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */
240
static void release_dirty_bitmap_helper(gpointer bitmap,
241
gpointer bs)
242
@@ -XXX,XX +XXX,XX @@ out:
243
244
return ret;
245
}
246
+
247
+/* store_bitmap_data()
248
+ * Store bitmap to image, filling bitmap table accordingly.
249
+ */
250
+static uint64_t *store_bitmap_data(BlockDriverState *bs,
251
+ BdrvDirtyBitmap *bitmap,
252
+ uint32_t *bitmap_table_size, Error **errp)
253
+{
254
+ int ret;
255
+ BDRVQcow2State *s = bs->opaque;
256
+ int64_t sector;
257
+ uint64_t sbc;
258
+ uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap);
259
+ const char *bm_name = bdrv_dirty_bitmap_name(bitmap);
260
+ uint8_t *buf = NULL;
261
+ BdrvDirtyBitmapIter *dbi;
262
+ uint64_t *tb;
263
+ uint64_t tb_size =
264
+ size_to_clusters(s,
265
+ bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size));
266
+
267
+ if (tb_size > BME_MAX_TABLE_SIZE ||
268
+ tb_size * s->cluster_size > BME_MAX_PHYS_SIZE)
269
+ {
270
+ error_setg(errp, "Bitmap '%s' is too big", bm_name);
271
+ return NULL;
272
+ }
273
+
274
+ tb = g_try_new0(uint64_t, tb_size);
275
+ if (tb == NULL) {
276
+ error_setg(errp, "No memory");
277
+ return NULL;
278
+ }
279
+
280
+ dbi = bdrv_dirty_iter_new(bitmap, 0);
281
+ buf = g_malloc(s->cluster_size);
282
+ sbc = sectors_covered_by_bitmap_cluster(s, bitmap);
283
+ assert(DIV_ROUND_UP(bm_size, sbc) == tb_size);
284
+
285
+ while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
286
+ uint64_t cluster = sector / sbc;
287
+ uint64_t end, write_size;
288
+ int64_t off;
289
+
290
+ sector = cluster * sbc;
291
+ end = MIN(bm_size, sector + sbc);
292
+ write_size =
293
+ bdrv_dirty_bitmap_serialization_size(bitmap, sector, end - sector);
294
+ assert(write_size <= s->cluster_size);
295
+
296
+ off = qcow2_alloc_clusters(bs, s->cluster_size);
297
+ if (off < 0) {
298
+ error_setg_errno(errp, -off,
299
+ "Failed to allocate clusters for bitmap '%s'",
300
+ bm_name);
301
+ goto fail;
302
+ }
303
+ tb[cluster] = off;
304
+
305
+ bdrv_dirty_bitmap_serialize_part(bitmap, buf, sector, end - sector);
306
+ if (write_size < s->cluster_size) {
307
+ memset(buf + write_size, 0, s->cluster_size - write_size);
308
+ }
309
+
310
+ ret = qcow2_pre_write_overlap_check(bs, 0, off, s->cluster_size);
311
+ if (ret < 0) {
312
+ error_setg_errno(errp, -ret, "Qcow2 overlap check failed");
313
+ goto fail;
314
+ }
315
+
316
+ ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size);
317
+ if (ret < 0) {
318
+ error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
319
+ bm_name);
320
+ goto fail;
321
+ }
322
+
323
+ if (end >= bm_size) {
324
+ break;
325
+ }
326
+
327
+ bdrv_set_dirty_iter(dbi, end);
328
+ }
329
+
330
+ *bitmap_table_size = tb_size;
331
+ g_free(buf);
332
+ bdrv_dirty_iter_free(dbi);
333
+
334
+ return tb;
335
+
336
+fail:
337
+ clear_bitmap_table(bs, tb, tb_size);
338
+ g_free(buf);
339
+ bdrv_dirty_iter_free(dbi);
340
+ g_free(tb);
341
+
342
+ return NULL;
343
+}
344
+
345
+/* store_bitmap()
346
+ * Store bm->dirty_bitmap to qcow2.
347
+ * Set bm->table_offset and bm->table_size accordingly.
348
+ */
349
+static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
350
+{
351
+ int ret;
352
+ uint64_t *tb;
353
+ int64_t tb_offset;
354
+ uint32_t tb_size;
355
+ BdrvDirtyBitmap *bitmap = bm->dirty_bitmap;
356
+ const char *bm_name;
357
+
358
+ assert(bitmap != NULL);
359
+
360
+ bm_name = bdrv_dirty_bitmap_name(bitmap);
361
+
362
+ tb = store_bitmap_data(bs, bitmap, &tb_size, errp);
363
+ if (tb == NULL) {
364
+ return -EINVAL;
365
+ }
366
+
367
+ assert(tb_size <= BME_MAX_TABLE_SIZE);
368
+ tb_offset = qcow2_alloc_clusters(bs, tb_size * sizeof(tb[0]));
369
+ if (tb_offset < 0) {
370
+ error_setg_errno(errp, -tb_offset,
371
+ "Failed to allocate clusters for bitmap '%s'",
372
+ bm_name);
373
+ goto fail;
374
+ }
375
+
376
+ ret = qcow2_pre_write_overlap_check(bs, 0, tb_offset,
377
+ tb_size * sizeof(tb[0]));
378
+ if (ret < 0) {
379
+ error_setg_errno(errp, -ret, "Qcow2 overlap check failed");
380
+ goto fail;
381
+ }
382
+
383
+ bitmap_table_to_be(tb, tb_size);
384
+ ret = bdrv_pwrite(bs->file, tb_offset, tb, tb_size * sizeof(tb[0]));
385
+ if (ret < 0) {
386
+ error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
387
+ bm_name);
388
+ goto fail;
389
+ }
390
+
391
+ g_free(tb);
392
+
393
+ bm->table.offset = tb_offset;
394
+ bm->table.size = tb_size;
395
+
396
+ return 0;
397
+
398
+fail:
399
+ clear_bitmap_table(bs, tb, tb_size);
400
+
401
+ if (tb_offset > 0) {
402
+ qcow2_free_clusters(bs, tb_offset, tb_size * sizeof(tb[0]),
403
+ QCOW2_DISCARD_OTHER);
404
+ }
405
+
406
+ g_free(tb);
407
+
408
+ return ret;
409
+}
410
+
411
+static Qcow2Bitmap *find_bitmap_by_name(Qcow2BitmapList *bm_list,
412
+ const char *name)
413
+{
414
+ Qcow2Bitmap *bm;
415
+
416
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
417
+ if (strcmp(name, bm->name) == 0) {
418
+ return bm;
419
+ }
420
+ }
421
+
422
+ return NULL;
423
+}
424
+
425
+void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
426
+{
427
+ BdrvDirtyBitmap *bitmap;
428
+ BDRVQcow2State *s = bs->opaque;
429
+ uint32_t new_nb_bitmaps = s->nb_bitmaps;
430
+ uint64_t new_dir_size = s->bitmap_directory_size;
431
+ int ret;
432
+ Qcow2BitmapList *bm_list;
433
+ Qcow2Bitmap *bm;
434
+ Qcow2BitmapTableList drop_tables;
435
+ Qcow2BitmapTable *tb, *tb_next;
436
+
437
+ if (!bdrv_has_changed_persistent_bitmaps(bs)) {
438
+ /* nothing to do */
439
+ return;
440
+ }
441
+
442
+ if (!can_write(bs)) {
443
+ error_setg(errp, "No write access");
444
+ return;
445
+ }
446
+
447
+ QSIMPLEQ_INIT(&drop_tables);
448
+
449
+ if (s->nb_bitmaps == 0) {
450
+ bm_list = bitmap_list_new();
451
+ } else {
452
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
453
+ s->bitmap_directory_size, errp);
454
+ if (bm_list == NULL) {
455
+ return;
456
+ }
457
+ }
458
+
459
+ /* check constraints and names */
460
+ for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL;
461
+ bitmap = bdrv_dirty_bitmap_next(bs, bitmap))
462
+ {
463
+ const char *name = bdrv_dirty_bitmap_name(bitmap);
464
+ uint32_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
465
+ Qcow2Bitmap *bm;
466
+
467
+ if (!bdrv_dirty_bitmap_get_persistance(bitmap) ||
468
+ bdrv_dirty_bitmap_readonly(bitmap))
469
+ {
470
+ continue;
471
+ }
472
+
473
+ if (check_constraints_on_bitmap(bs, name, granularity, errp) < 0) {
474
+ error_prepend(errp, "Bitmap '%s' doesn't satisfy the constraints: ",
475
+ name);
476
+ goto fail;
477
+ }
478
+
479
+ bm = find_bitmap_by_name(bm_list, name);
480
+ if (bm == NULL) {
481
+ if (++new_nb_bitmaps > QCOW2_MAX_BITMAPS) {
482
+ error_setg(errp, "Too many persistent bitmaps");
483
+ goto fail;
484
+ }
485
+
486
+ new_dir_size += calc_dir_entry_size(strlen(name), 0);
487
+ if (new_dir_size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) {
488
+ error_setg(errp, "Bitmap directory is too large");
489
+ goto fail;
490
+ }
491
+
492
+ bm = g_new0(Qcow2Bitmap, 1);
493
+ bm->name = g_strdup(name);
494
+ QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry);
495
+ } else {
496
+ if (!(bm->flags & BME_FLAG_IN_USE)) {
497
+ error_setg(errp, "Bitmap '%s' already exists in the image",
498
+ name);
499
+ goto fail;
500
+ }
501
+ tb = g_memdup(&bm->table, sizeof(bm->table));
502
+ bm->table.offset = 0;
503
+ bm->table.size = 0;
504
+ QSIMPLEQ_INSERT_TAIL(&drop_tables, tb, entry);
505
+ }
506
+ bm->flags = bdrv_dirty_bitmap_get_autoload(bitmap) ? BME_FLAG_AUTO : 0;
507
+ bm->granularity_bits = ctz32(bdrv_dirty_bitmap_granularity(bitmap));
508
+ bm->dirty_bitmap = bitmap;
509
+ }
510
+
511
+ /* allocate clusters and store bitmaps */
512
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
513
+ if (bm->dirty_bitmap == NULL) {
514
+ continue;
515
+ }
516
+
517
+ ret = store_bitmap(bs, bm, errp);
518
+ if (ret < 0) {
519
+ goto fail;
520
+ }
521
+ }
522
+
523
+ ret = update_ext_header_and_dir(bs, bm_list);
524
+ if (ret < 0) {
525
+ error_setg_errno(errp, -ret, "Failed to update bitmap extension");
526
+ goto fail;
527
+ }
528
+
529
+ /* Bitmap directory was successfully updated, so, old data can be dropped.
530
+ * TODO it is better to reuse these clusters */
531
+ QSIMPLEQ_FOREACH_SAFE(tb, &drop_tables, entry, tb_next) {
532
+ free_bitmap_clusters(bs, tb);
533
+ g_free(tb);
534
+ }
535
+
536
+ bitmap_list_free(bm_list);
537
+ return;
538
+
539
+fail:
540
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
541
+ if (bm->dirty_bitmap == NULL || bm->table.offset == 0) {
542
+ continue;
543
+ }
544
+
545
+ free_bitmap_clusters(bs, &bm->table);
546
+ }
547
+
548
+ QSIMPLEQ_FOREACH_SAFE(tb, &drop_tables, entry, tb_next) {
549
+ g_free(tb);
550
+ }
551
+
552
+ bitmap_list_free(bm_list);
553
+}
554
diff --git a/block/qcow2.c b/block/qcow2.c
555
index XXXXXXX..XXXXXXX 100644
556
--- a/block/qcow2.c
557
+++ b/block/qcow2.c
558
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
559
{
146
{
560
BDRVQcow2State *s = bs->opaque;
147
JOB_LOCK_GUARD();
561
int ret, result = 0;
148
block_job_iostatus_reset_locked(job);
562
+ Error *local_err = NULL;
563
564
ret = qcow2_cache_flush(bs, s->l2_table_cache);
565
if (ret) {
566
@@ -XXX,XX +XXX,XX @@ static int qcow2_inactivate(BlockDriverState *bs)
567
strerror(-ret));
568
}
569
570
+ qcow2_store_persistent_dirty_bitmaps(bs, &local_err);
571
+ if (local_err != NULL) {
572
+ result = -EINVAL;
573
+ error_report_err(local_err);
574
+ error_report("Persistent bitmaps are lost for node '%s'",
575
+ bdrv_get_device_or_node_name(bs));
576
+ }
577
+
578
if (result == 0) {
579
qcow2_mark_clean(bs);
580
}
581
diff --git a/block/qcow2.h b/block/qcow2.h
582
index XXXXXXX..XXXXXXX 100644
583
--- a/block/qcow2.h
584
+++ b/block/qcow2.h
585
@@ -XXX,XX +XXX,XX @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
586
int64_t *refcount_table_size);
587
bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
588
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
589
+void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
590
591
#endif
592
--
149
--
593
1.8.3.1
150
2.37.3
594
595
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Realize bdrv_reopen_bitmaps_rw interface.
3
These public functions are not used anywhere, thus can be dropped.
4
Also, since this is the final job API that doesn't use AioContext
5
lock and replaces it with job_lock, adjust all remaining function
6
documentation to clearly specify if the job lock is taken or not.
4
7
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Also document the locking requirements for a few functions
6
Reviewed-by: John Snow <jsnow@redhat.com>
9
where the second version is not removed.
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
8
Message-id: 20170628120530.31251-15-vsementsov@virtuozzo.com
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20220926093214.506243-22-eesposit@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
17
---
11
block/qcow2-bitmap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++
18
include/qemu/job.h | 110 +++++++++++++------------------------
12
block/qcow2.c | 2 ++
19
job.c | 107 ++----------------------------------
13
block/qcow2.h | 1 +
20
tests/unit/test-blockjob.c | 4 +-
14
3 files changed, 64 insertions(+)
21
3 files changed, 46 insertions(+), 175 deletions(-)
15
22
16
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
23
diff --git a/include/qemu/job.h b/include/qemu/job.h
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-bitmap.c
25
--- a/include/qemu/job.h
19
+++ b/block/qcow2-bitmap.c
26
+++ b/include/qemu/job.h
20
@@ -XXX,XX +XXX,XX @@ fail:
27
@@ -XXX,XX +XXX,XX @@ JobTxn *job_txn_new(void);
21
28
/**
29
* Release a reference that was previously acquired with job_txn_add_job or
30
* job_txn_new. If it's the last reference to the object, it will be freed.
31
+ *
32
+ * Called with job lock *not* held.
33
*/
34
void job_txn_unref(JobTxn *txn);
35
36
@@ -XXX,XX +XXX,XX @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn,
37
/**
38
* Add a reference to Job refcnt, it will be decreased with job_unref, and then
39
* be freed if it comes to be the last reference.
40
+ *
41
+ * Called with job lock held.
42
*/
43
-void job_ref(Job *job);
44
-
45
-/* Same as job_ref(), but called with job lock held. */
46
void job_ref_locked(Job *job);
47
48
/**
49
- * Release a reference that was previously acquired with job_ref() or
50
+ * Release a reference that was previously acquired with job_ref_locked() or
51
* job_create(). If it's the last reference to the object, it will be freed.
52
*
53
* Takes AioContext lock internally to invoke a job->driver callback.
54
+ * Called with job lock held.
55
*/
56
-void job_unref(Job *job);
57
-
58
-/* Same as job_unref(), but called with job lock held. */
59
void job_unref_locked(Job *job);
60
61
/**
62
@@ -XXX,XX +XXX,XX @@ void job_progress_increase_remaining(Job *job, uint64_t delta);
63
* Conditionally enter the job coroutine if the job is ready to run, not
64
* already busy and fn() returns true. fn() is called while under the job_lock
65
* critical section.
66
- */
67
-void job_enter_cond(Job *job, bool(*fn)(Job *job));
68
-
69
-/*
70
- * Same as job_enter_cond(), but called with job lock held.
71
- * Might release the lock temporarily.
72
+ *
73
+ * Called with job lock held, but might release it temporarily.
74
*/
75
void job_enter_cond_locked(Job *job, bool(*fn)(Job *job));
76
77
@@ -XXX,XX +XXX,XX @@ bool job_cancel_requested(Job *job);
78
79
/**
80
* Returns whether the job is in a completed state.
81
- * Called with job_mutex *not* held.
82
+ * Called with job lock held.
83
*/
84
-bool job_is_completed(Job *job);
85
-
86
-/* Same as job_is_completed(), but called with job lock held. */
87
bool job_is_completed_locked(Job *job);
88
89
/**
90
@@ -XXX,XX +XXX,XX @@ bool job_is_ready_locked(Job *job);
91
/**
92
* Request @job to pause at the next pause point. Must be paired with
93
* job_resume(). If the job is supposed to be resumed by user action, call
94
- * job_user_pause() instead.
95
+ * job_user_pause_locked() instead.
96
+ *
97
+ * Called with job lock *not* held.
98
*/
99
void job_pause(Job *job);
100
101
/* Same as job_pause(), but called with job lock held. */
102
void job_pause_locked(Job *job);
103
104
-/** Resumes a @job paused with job_pause. */
105
+/** Resumes a @job paused with job_pause. Called with job lock *not* held. */
106
void job_resume(Job *job);
107
108
/*
109
@@ -XXX,XX +XXX,XX @@ void job_resume_locked(Job *job);
110
/**
111
* Asynchronously pause the specified @job.
112
* Do not allow a resume until a matching call to job_user_resume.
113
+ * Called with job lock held.
114
*/
115
-void job_user_pause(Job *job, Error **errp);
116
-
117
-/* Same as job_user_pause(), but called with job lock held. */
118
void job_user_pause_locked(Job *job, Error **errp);
119
120
-/** Returns true if the job is user-paused. */
121
-bool job_user_paused(Job *job);
122
-
123
-/* Same as job_user_paused(), but called with job lock held. */
124
+/**
125
+ * Returns true if the job is user-paused.
126
+ * Called with job lock held.
127
+ */
128
bool job_user_paused_locked(Job *job);
129
130
/**
131
* Resume the specified @job.
132
- * Must be paired with a preceding job_user_pause.
133
- */
134
-void job_user_resume(Job *job, Error **errp);
135
-
136
-/*
137
- * Same as job_user_resume(), but called with job lock held.
138
- * Might release the lock temporarily.
139
+ * Must be paired with a preceding job_user_pause_locked.
140
+ * Called with job lock held, but might release it temporarily.
141
*/
142
void job_user_resume_locked(Job *job, Error **errp);
143
144
@@ -XXX,XX +XXX,XX @@ void job_user_resume_locked(Job *job, Error **errp);
145
* first one if @job is %NULL.
146
*
147
* Returns the requested job, or %NULL if there are no more jobs left.
148
+ * Called with job lock *not* held.
149
*/
150
Job *job_next(Job *job);
151
152
@@ -XXX,XX +XXX,XX @@ Job *job_next_locked(Job *job);
153
* Get the job identified by @id (which must not be %NULL).
154
*
155
* Returns the requested job, or %NULL if it doesn't exist.
156
+ * Called with job lock held.
157
*/
158
-Job *job_get(const char *id);
159
-
160
-/* Same as job_get(), but called with job lock held. */
161
Job *job_get_locked(const char *id);
162
163
/**
164
* Check whether the verb @verb can be applied to @job in its current state.
165
* Returns 0 if the verb can be applied; otherwise errp is set and -EPERM
166
* returned.
167
+ *
168
+ * Called with job lock held.
169
*/
170
-int job_apply_verb(Job *job, JobVerb verb, Error **errp);
171
-
172
-/* Same as job_apply_verb, but called with job lock held. */
173
int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp);
174
175
/**
176
@@ -XXX,XX +XXX,XX @@ void job_early_fail(Job *job);
177
*/
178
void job_transition_to_ready(Job *job);
179
180
-/** Asynchronously complete the specified @job. */
181
-void job_complete(Job *job, Error **errp);
182
-
183
-/*
184
- * Same as job_complete(), but called with job lock held.
185
- * Might release the lock temporarily.
186
+/**
187
+ * Asynchronously complete the specified @job.
188
+ * Called with job lock held, but might release it temporarily.
189
*/
190
void job_complete_locked(Job *job, Error **errp);
191
192
/**
193
* Asynchronously cancel the specified @job. If @force is true, the job should
194
* be cancelled immediately without waiting for a consistent state.
195
+ * Called with job lock held.
196
*/
197
-void job_cancel(Job *job, bool force);
198
-
199
-/* Same as job_cancel(), but called with job lock held. */
200
void job_cancel_locked(Job *job, bool force);
201
202
/**
203
- * Cancels the specified job like job_cancel(), but may refuse to do so if the
204
- * operation isn't meaningful in the current state of the job.
205
+ * Cancels the specified job like job_cancel_locked(), but may refuse
206
+ * to do so if the operation isn't meaningful in the current state of the job.
207
+ * Called with job lock held.
208
*/
209
-void job_user_cancel(Job *job, bool force, Error **errp);
210
-
211
-/* Same as job_user_cancel(), but called with job lock held. */
212
void job_user_cancel_locked(Job *job, bool force, Error **errp);
213
214
/**
215
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
216
217
/**
218
* @job: The job to be completed.
219
- * @errp: Error object which may be set by job_complete(); this is not
220
+ * @errp: Error object which may be set by job_complete_locked(); this is not
221
* necessarily set on every error, the job return value has to be
222
* checked as well.
223
*
224
@@ -XXX,XX +XXX,XX @@ void job_cancel_sync_all(void);
225
* function).
226
*
227
* Returns the return value from the job.
228
- * Called with job_lock *not* held.
229
+ * Called with job_lock held.
230
*/
231
-int job_complete_sync(Job *job, Error **errp);
232
-
233
-/* Same as job_complete_sync, but called with job lock held. */
234
int job_complete_sync_locked(Job *job, Error **errp);
235
236
/**
237
@@ -XXX,XX +XXX,XX @@ int job_complete_sync_locked(Job *job, Error **errp);
238
* FIXME: Make the below statement universally true:
239
* For jobs that support the manual workflow mode, all graph changes that occur
240
* as a result will occur after this command and before a successful reply.
241
+ *
242
+ * Called with job lock held.
243
*/
244
-void job_finalize(Job *job, Error **errp);
245
-
246
-/* Same as job_finalize(), but called with job lock held. */
247
void job_finalize_locked(Job *job, Error **errp);
248
249
/**
250
* Remove the concluded @job from the query list and resets the passed pointer
251
* to %NULL. Returns an error if the job is not actually concluded.
252
+ *
253
+ * Called with job lock held.
254
*/
255
-void job_dismiss(Job **job, Error **errp);
256
-
257
-/* Same as job_dismiss(), but called with job lock held. */
258
void job_dismiss_locked(Job **job, Error **errp);
259
260
/**
261
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **job, Error **errp);
262
* Returns 0 if the job is successfully completed, -ECANCELED if the job was
263
* cancelled before completing, and -errno in other error cases.
264
*
265
- * Called with job_lock *not* held.
266
- */
267
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp),
268
- Error **errp);
269
-
270
-/*
271
- * Same as job_finish_sync(), but called with job lock held.
272
- * Might release the lock temporarily.
273
+ * Called with job_lock held, but might release it temporarily.
274
*/
275
int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp),
276
Error **errp);
277
diff --git a/job.c b/job.c
278
index XXXXXXX..XXXXXXX 100644
279
--- a/job.c
280
+++ b/job.c
281
@@ -XXX,XX +XXX,XX @@ int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp)
282
return -EPERM;
283
}
284
285
-int job_apply_verb(Job *job, JobVerb verb, Error **errp)
286
-{
287
- JOB_LOCK_GUARD();
288
- return job_apply_verb_locked(job, verb, errp);
289
-}
290
-
291
JobType job_type(const Job *job)
292
{
293
return job->driver->job_type;
294
@@ -XXX,XX +XXX,XX @@ bool job_is_completed_locked(Job *job)
22
return false;
295
return false;
23
}
296
}
24
+
297
25
+int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp)
298
-bool job_is_completed(Job *job)
26
+{
299
+static bool job_is_completed(Job *job)
27
+ BDRVQcow2State *s = bs->opaque;
300
{
28
+ Qcow2BitmapList *bm_list;
301
JOB_LOCK_GUARD();
29
+ Qcow2Bitmap *bm;
302
return job_is_completed_locked(job);
30
+ GSList *ro_dirty_bitmaps = NULL;
303
@@ -XXX,XX +XXX,XX @@ Job *job_get_locked(const char *id)
31
+ int ret = 0;
304
return NULL;
32
+
305
}
33
+ if (s->nb_bitmaps == 0) {
306
34
+ /* No bitmaps - nothing to do */
307
-Job *job_get(const char *id)
35
+ return 0;
308
-{
36
+ }
309
- JOB_LOCK_GUARD();
37
+
310
- return job_get_locked(id);
38
+ if (!can_write(bs)) {
311
-}
39
+ error_setg(errp, "Can't write to the image on reopening bitmaps rw");
312
-
40
+ return -EINVAL;
313
void job_set_aio_context(Job *job, AioContext *ctx)
41
+ }
314
{
42
+
315
/* protect against read in job_finish_sync_locked and job_start */
43
+ bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
316
@@ -XXX,XX +XXX,XX @@ void job_ref_locked(Job *job)
44
+ s->bitmap_directory_size, errp);
317
++job->refcnt;
45
+ if (bm_list == NULL) {
318
}
46
+ return -EINVAL;
319
47
+ }
320
-void job_ref(Job *job)
48
+
321
-{
49
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
322
- JOB_LOCK_GUARD();
50
+ if (!(bm->flags & BME_FLAG_IN_USE)) {
323
- job_ref_locked(job);
51
+ BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(bs, bm->name);
324
-}
52
+ if (bitmap == NULL) {
325
-
53
+ continue;
326
void job_unref_locked(Job *job)
54
+ }
327
{
55
+
328
GLOBAL_STATE_CODE();
56
+ if (!bdrv_dirty_bitmap_readonly(bitmap)) {
329
@@ -XXX,XX +XXX,XX @@ void job_unref_locked(Job *job)
57
+ error_setg(errp, "Bitmap %s is not readonly but not marked"
330
}
58
+ "'IN_USE' in the image. Something went wrong,"
331
}
59
+ "all the bitmaps may be corrupted", bm->name);
332
60
+ ret = -EINVAL;
333
-void job_unref(Job *job)
61
+ goto out;
334
-{
62
+ }
335
- JOB_LOCK_GUARD();
63
+
336
- job_unref_locked(job);
64
+ bm->flags |= BME_FLAG_IN_USE;
337
-}
65
+ ro_dirty_bitmaps = g_slist_append(ro_dirty_bitmaps, bitmap);
338
-
66
+ }
339
void job_progress_update(Job *job, uint64_t done)
67
+ }
340
{
68
+
341
progress_work_done(&job->progress, done);
69
+ if (ro_dirty_bitmaps != NULL) {
342
@@ -XXX,XX +XXX,XX @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job))
70
+ /* in_use flags must be updated */
343
job_lock();
71
+ ret = update_ext_header_and_dir_in_place(bs, bm_list);
344
}
72
+ if (ret < 0) {
345
73
+ error_setg_errno(errp, -ret, "Can't update bitmap directory");
346
-void job_enter_cond(Job *job, bool(*fn)(Job *job))
74
+ goto out;
347
-{
75
+ }
348
- JOB_LOCK_GUARD();
76
+ g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false);
349
- job_enter_cond_locked(job, fn);
77
+ }
350
-}
78
+
351
-
79
+out:
352
void job_enter(Job *job)
80
+ g_slist_free(ro_dirty_bitmaps);
353
{
81
+ bitmap_list_free(bm_list);
354
JOB_LOCK_GUARD();
82
+
355
@@ -XXX,XX +XXX,XX @@ void coroutine_fn job_pause_point(Job *job)
83
+ return ret;
356
job_pause_point_locked(job);
84
+}
357
}
85
diff --git a/block/qcow2.c b/block/qcow2.c
358
359
-static void coroutine_fn job_yield_locked(Job *job)
360
+void coroutine_fn job_yield(Job *job)
361
{
362
+ JOB_LOCK_GUARD();
363
assert(job->busy);
364
365
/* Check cancellation *before* setting busy = false, too! */
366
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_yield_locked(Job *job)
367
job_pause_point_locked(job);
368
}
369
370
-void coroutine_fn job_yield(Job *job)
371
-{
372
- JOB_LOCK_GUARD();
373
- job_yield_locked(job);
374
-}
375
-
376
void coroutine_fn job_sleep_ns(Job *job, int64_t ns)
377
{
378
JOB_LOCK_GUARD();
379
@@ -XXX,XX +XXX,XX @@ void job_user_pause_locked(Job *job, Error **errp)
380
job_pause_locked(job);
381
}
382
383
-void job_user_pause(Job *job, Error **errp)
384
-{
385
- JOB_LOCK_GUARD();
386
- job_user_pause_locked(job, errp);
387
-}
388
-
389
bool job_user_paused_locked(Job *job)
390
{
391
return job->user_paused;
392
}
393
394
-bool job_user_paused(Job *job)
395
-{
396
- JOB_LOCK_GUARD();
397
- return job_user_paused_locked(job);
398
-}
399
-
400
void job_user_resume_locked(Job *job, Error **errp)
401
{
402
assert(job);
403
@@ -XXX,XX +XXX,XX @@ void job_user_resume_locked(Job *job, Error **errp)
404
job_resume_locked(job);
405
}
406
407
-void job_user_resume(Job *job, Error **errp)
408
-{
409
- JOB_LOCK_GUARD();
410
- job_user_resume_locked(job, errp);
411
-}
412
-
413
/* Called with job_mutex held, but releases it temporarily. */
414
static void job_do_dismiss_locked(Job *job)
415
{
416
@@ -XXX,XX +XXX,XX @@ void job_dismiss_locked(Job **jobptr, Error **errp)
417
*jobptr = NULL;
418
}
419
420
-void job_dismiss(Job **jobptr, Error **errp)
421
-{
422
- JOB_LOCK_GUARD();
423
- job_dismiss_locked(jobptr, errp);
424
-}
425
-
426
void job_early_fail(Job *job)
427
{
428
JOB_LOCK_GUARD();
429
@@ -XXX,XX +XXX,XX @@ void job_finalize_locked(Job *job, Error **errp)
430
job_do_finalize_locked(job);
431
}
432
433
-void job_finalize(Job *job, Error **errp)
434
-{
435
- JOB_LOCK_GUARD();
436
- job_finalize_locked(job, errp);
437
-}
438
-
439
/* Called with job_mutex held. */
440
static int job_transition_to_pending_locked(Job *job)
441
{
442
@@ -XXX,XX +XXX,XX @@ void job_cancel_locked(Job *job, bool force)
443
}
444
}
445
446
-void job_cancel(Job *job, bool force)
447
-{
448
- JOB_LOCK_GUARD();
449
- job_cancel_locked(job, force);
450
-}
451
-
452
void job_user_cancel_locked(Job *job, bool force, Error **errp)
453
{
454
if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) {
455
@@ -XXX,XX +XXX,XX @@ void job_user_cancel_locked(Job *job, bool force, Error **errp)
456
job_cancel_locked(job, force);
457
}
458
459
-void job_user_cancel(Job *job, bool force, Error **errp)
460
-{
461
- JOB_LOCK_GUARD();
462
- job_user_cancel_locked(job, force, errp);
463
-}
464
-
465
-/* A wrapper around job_cancel() taking an Error ** parameter so it may be
466
- * used with job_finish_sync() without the need for (rather nasty) function
467
- * pointer casts there.
468
+/* A wrapper around job_cancel_locked() taking an Error ** parameter so it may
469
+ * be used with job_finish_sync_locked() without the need for (rather nasty)
470
+ * function pointer casts there.
471
*
472
* Called with job_mutex held.
473
*/
474
@@ -XXX,XX +XXX,XX @@ int job_complete_sync_locked(Job *job, Error **errp)
475
return job_finish_sync_locked(job, job_complete_locked, errp);
476
}
477
478
-int job_complete_sync(Job *job, Error **errp)
479
-{
480
- JOB_LOCK_GUARD();
481
- return job_complete_sync_locked(job, errp);
482
-}
483
-
484
void job_complete_locked(Job *job, Error **errp)
485
{
486
/* Should not be reachable via external interface for internal jobs */
487
@@ -XXX,XX +XXX,XX @@ void job_complete_locked(Job *job, Error **errp)
488
job_lock();
489
}
490
491
-void job_complete(Job *job, Error **errp)
492
-{
493
- JOB_LOCK_GUARD();
494
- job_complete_locked(job, errp);
495
-}
496
-
497
int job_finish_sync_locked(Job *job,
498
void (*finish)(Job *, Error **errp),
499
Error **errp)
500
@@ -XXX,XX +XXX,XX @@ int job_finish_sync_locked(Job *job,
501
job_unref_locked(job);
502
return ret;
503
}
504
-
505
-int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp)
506
-{
507
- JOB_LOCK_GUARD();
508
- return job_finish_sync_locked(job, finish, errp);
509
-}
510
diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c
86
index XXXXXXX..XXXXXXX 100644
511
index XXXXXXX..XXXXXXX 100644
87
--- a/block/qcow2.c
512
--- a/tests/unit/test-blockjob.c
88
+++ b/block/qcow2.c
513
+++ b/tests/unit/test-blockjob.c
89
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
514
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver test_yielding_driver = {
90
91
.bdrv_detach_aio_context = qcow2_detach_aio_context,
92
.bdrv_attach_aio_context = qcow2_attach_aio_context,
93
+
94
+ .bdrv_reopen_bitmaps_rw = qcow2_reopen_bitmaps_rw,
95
};
515
};
96
516
97
static void bdrv_qcow2_init(void)
517
/*
98
diff --git a/block/qcow2.h b/block/qcow2.h
518
- * Test that job_complete() works even on jobs that are in a paused
99
index XXXXXXX..XXXXXXX 100644
519
+ * Test that job_complete_locked() works even on jobs that are in a paused
100
--- a/block/qcow2.h
520
* state (i.e., STANDBY).
101
+++ b/block/qcow2.h
521
*
102
@@ -XXX,XX +XXX,XX @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
522
* To do this, run YieldingJob in an IO thread, get it into the READY
103
void **refcount_table,
523
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver test_yielding_driver = {
104
int64_t *refcount_table_size);
524
* acquire the context so the job will not be entered and will thus
105
bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
525
* remain on STANDBY.
106
+int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
526
*
107
527
- * job_complete() should still work without error.
108
#endif
528
+ * job_complete_locked() should still work without error.
529
*
530
* Note that on the QMP interface, it is impossible to lock an IO
531
* thread before a drained section ends. In practice, the
109
--
532
--
110
1.8.3.1
533
2.37.3
111
112
diff view generated by jsdifflib
1
From: Hervé Poussineau <hpoussin@reactos.org>
1
The field is unused (only ever set, but never read) since commit
2
ac9185603. Additionally, the commit message of commit 34fa110e already
3
explained earlier why it's unreliable. Remove it.
2
4
3
FAT12/FAT16 root directory is two sectors in size, which allows only 512 directory entries.
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Prevent QEMU startup if too much files exist, instead of overflowing root directory.
6
Message-Id: <20220923142838.91043-1-kwolf@redhat.com>
5
6
Also introduce variable root_entries, which will be required for FAT32.
7
8
Fixes: https://bugs.launchpad.net/qemu/+bug/1599539/comments/4
9
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
block/vvfat.c | 26 +++++++++++++++++---------
9
block/file-posix.c | 9 ---------
13
1 file changed, 17 insertions(+), 9 deletions(-)
10
1 file changed, 9 deletions(-)
14
11
15
diff --git a/block/vvfat.c b/block/vvfat.c
12
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/block/vvfat.c
14
--- a/block/file-posix.c
18
+++ b/block/vvfat.c
15
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVVVFATState {
16
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
20
unsigned int cluster_size;
17
21
unsigned int sectors_per_cluster;
18
bool has_discard:1;
22
unsigned int sectors_per_fat;
19
bool has_write_zeroes:1;
23
- unsigned int sectors_of_root_directory;
20
- bool discard_zeroes:1;
24
uint32_t last_cluster_of_root_directory;
21
bool use_linux_aio:1;
25
+ /* how many entries are available in root directory (0 for FAT32) */
22
bool use_linux_io_uring:1;
26
+ uint16_t root_entries;
23
int page_cache_inconsistent; /* errno from fdatasync failure */
27
uint32_t sector_count; /* total number of sectors of the partition */
24
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
28
uint32_t cluster_count; /* total number of clusters of this partition */
25
ret = -EINVAL;
29
uint32_t max_fat_value;
26
goto fail;
30
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
27
} else {
31
int is_dot=!strcmp(entry->d_name,".");
28
- s->discard_zeroes = true;
32
int is_dotdot=!strcmp(entry->d_name,"..");
29
s->has_fallocate = true;
33
30
}
34
+ if (first_cluster == 0 && s->directory.next >= s->root_entries - 1) {
31
} else {
35
+ fprintf(stderr, "Too many entries in root directory\n");
32
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
36
+ closedir(dir);
37
+ return -2;
38
+ }
39
+
40
if(first_cluster == 0 && (is_dotdot || is_dot))
41
continue;
42
43
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
44
memset(direntry,0,sizeof(direntry_t));
45
}
33
}
46
34
47
-/* TODO: if there are more entries, bootsector has to be adjusted! */
35
if (S_ISBLK(st.st_mode)) {
48
-#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)
36
-#ifdef BLKDISCARDZEROES
49
- if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {
37
- unsigned int arg;
50
+ if (s->fat_type != 32 &&
38
- if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg) {
51
+ mapping_index == 0 &&
39
- s->discard_zeroes = true;
52
+ s->directory.next < s->root_entries) {
40
- }
53
/* root directory */
41
-#endif
54
int cur = s->directory.next;
42
#ifdef __linux__
55
- array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
43
/* On Linux 3.10, BLKDISCARD leaves stale data in the page cache. Do
56
- s->directory.next = ROOT_ENTRIES;
44
* not rely on the contents of discarded blocks unless using O_DIRECT.
57
+ array_ensure_allocated(&(s->directory), s->root_entries - 1);
45
* Same for BLKZEROOUT.
58
+ s->directory.next = s->root_entries;
46
*/
59
memset(array_get(&(s->directory), cur), 0,
47
if (!(bs->open_flags & BDRV_O_NOCACHE)) {
60
- (ROOT_ENTRIES - cur) * sizeof(direntry_t));
48
- s->discard_zeroes = false;
61
+ (s->root_entries - cur) * sizeof(direntry_t));
49
s->has_write_zeroes = false;
62
}
50
}
63
51
#endif
64
/* re-get the mapping, since s->mapping was possibly realloc()ed */
65
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
66
/* Now build FAT, and write back information into directory */
67
init_fat(s);
68
69
+ /* TODO: if there are more entries, bootsector has to be adjusted! */
70
+ s->root_entries = 0x02 * 0x10 * s->sectors_per_cluster;
71
s->cluster_count=sector2cluster(s, s->sector_count);
72
73
mapping = array_get_next(&(s->mapping));
74
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
75
}
76
77
mapping = array_get(&(s->mapping), 0);
78
- s->sectors_of_root_directory = mapping->end * s->sectors_per_cluster;
79
s->last_cluster_of_root_directory = mapping->end;
80
81
/* the FAT signature */
82
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
83
bootsector->sectors_per_cluster=s->sectors_per_cluster;
84
bootsector->reserved_sectors=cpu_to_le16(1);
85
bootsector->number_of_fats=0x2; /* number of FATs */
86
- bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
87
+ bootsector->root_entries = cpu_to_le16(s->root_entries);
88
bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
89
/* media descriptor: hard disk=0xf8, floppy=0xf0 */
90
bootsector->media_type = (s->offset_to_bootsector > 0 ? 0xf8 : 0xf0);
91
--
52
--
92
1.8.3.1
53
2.37.3
93
94
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
The '-e' and '-6' options to the 'create' & 'convert' commands were
4
"deprecated" in favour of the more generic '-o' option many years ago:
5
6
commit eec77d9e712bd4157a4e1c0b5a9249d168add738
7
Author: Jes Sorensen <Jes.Sorensen@redhat.com>
8
Date: Tue Dec 7 17:44:34 2010 +0100
9
10
qemu-img: Deprecate obsolete -6 and -e options
11
12
Except this was never actually a deprecation, which would imply giving
13
the user a warning while the functionality continues to work for a
14
number of releases before eventual removal. Instead the options were
15
immediately turned into an error + exit. Given that the functionality
16
is already broken, there's no point in keeping these psuedo-deprecation
17
messages around any longer.
18
19
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
qemu-img.c | 20 ++------------------
23
1 file changed, 2 insertions(+), 18 deletions(-)
24
25
diff --git a/qemu-img.c b/qemu-img.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
28
+++ b/qemu-img.c
29
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
30
{"object", required_argument, 0, OPTION_OBJECT},
31
{0, 0, 0, 0}
32
};
33
- c = getopt_long(argc, argv, ":F:b:f:he6o:q",
34
+ c = getopt_long(argc, argv, ":F:b:f:ho:q",
35
long_options, NULL);
36
if (c == -1) {
37
break;
38
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
39
case 'f':
40
fmt = optarg;
41
break;
42
- case 'e':
43
- error_report("option -e is deprecated, please use \'-o "
44
- "encryption\' instead!");
45
- goto fail;
46
- case '6':
47
- error_report("option -6 is deprecated, please use \'-o "
48
- "compat6\' instead!");
49
- goto fail;
50
case 'o':
51
if (!is_valid_option_list(optarg)) {
52
error_report("Invalid option list: %s", optarg);
53
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
54
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
55
{0, 0, 0, 0}
56
};
57
- c = getopt_long(argc, argv, ":hf:O:B:ce6o:s:l:S:pt:T:qnm:WU",
58
+ c = getopt_long(argc, argv, ":hf:O:B:co:s:l:S:pt:T:qnm:WU",
59
long_options, NULL);
60
if (c == -1) {
61
break;
62
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
63
case 'c':
64
s.compressed = true;
65
break;
66
- case 'e':
67
- error_report("option -e is deprecated, please use \'-o "
68
- "encryption\' instead!");
69
- goto fail_getopt;
70
- case '6':
71
- error_report("option -6 is deprecated, please use \'-o "
72
- "compat6\' instead!");
73
- goto fail_getopt;
74
case 'o':
75
if (!is_valid_option_list(optarg)) {
76
error_report("Invalid option list: %s", optarg);
77
--
78
1.8.3.1
79
80
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually converting to byte-based interfaces, as they are
4
easier to reason about than sector-based. Continue by converting an
5
internal structure (no semantic change), and all references to
6
tracking progress. Drop a redundant local variable bytes_per_cluster.
7
8
Signed-off-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Jeff Cody <jcody@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/backup.c | 33 +++++++++++++++------------------
15
1 file changed, 15 insertions(+), 18 deletions(-)
16
17
diff --git a/block/backup.c b/block/backup.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/backup.c
20
+++ b/block/backup.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
22
BlockdevOnError on_source_error;
23
BlockdevOnError on_target_error;
24
CoRwlock flush_rwlock;
25
- uint64_t sectors_read;
26
+ uint64_t bytes_read;
27
unsigned long *done_bitmap;
28
int64_t cluster_size;
29
bool compress;
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
31
void *bounce_buffer = NULL;
32
int ret = 0;
33
int64_t sectors_per_cluster = cluster_size_sectors(job);
34
- int64_t bytes_per_cluster = sectors_per_cluster * BDRV_SECTOR_SIZE;
35
- int64_t start, end;
36
- int n;
37
+ int64_t start, end; /* clusters */
38
+ int n; /* bytes */
39
40
qemu_co_rwlock_rdlock(&job->flush_rwlock);
41
42
start = sector_num / sectors_per_cluster;
43
end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
44
45
- trace_backup_do_cow_enter(job, start * bytes_per_cluster,
46
+ trace_backup_do_cow_enter(job, start * job->cluster_size,
47
sector_num * BDRV_SECTOR_SIZE,
48
nb_sectors * BDRV_SECTOR_SIZE);
49
50
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
51
52
for (; start < end; start++) {
53
if (test_bit(start, job->done_bitmap)) {
54
- trace_backup_do_cow_skip(job, start * bytes_per_cluster);
55
+ trace_backup_do_cow_skip(job, start * job->cluster_size);
56
continue; /* already copied */
57
}
58
59
- trace_backup_do_cow_process(job, start * bytes_per_cluster);
60
+ trace_backup_do_cow_process(job, start * job->cluster_size);
61
62
- n = MIN(sectors_per_cluster,
63
- job->common.len / BDRV_SECTOR_SIZE -
64
- start * sectors_per_cluster);
65
+ n = MIN(job->cluster_size,
66
+ job->common.len - start * job->cluster_size);
67
68
if (!bounce_buffer) {
69
bounce_buffer = blk_blockalign(blk, job->cluster_size);
70
}
71
iov.iov_base = bounce_buffer;
72
- iov.iov_len = n * BDRV_SECTOR_SIZE;
73
+ iov.iov_len = n;
74
qemu_iovec_init_external(&bounce_qiov, &iov, 1);
75
76
ret = blk_co_preadv(blk, start * job->cluster_size,
77
bounce_qiov.size, &bounce_qiov,
78
is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
79
if (ret < 0) {
80
- trace_backup_do_cow_read_fail(job, start * bytes_per_cluster, ret);
81
+ trace_backup_do_cow_read_fail(job, start * job->cluster_size, ret);
82
if (error_is_read) {
83
*error_is_read = true;
84
}
85
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
86
job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
87
}
88
if (ret < 0) {
89
- trace_backup_do_cow_write_fail(job, start * bytes_per_cluster, ret);
90
+ trace_backup_do_cow_write_fail(job, start * job->cluster_size, ret);
91
if (error_is_read) {
92
*error_is_read = false;
93
}
94
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
95
/* Publish progress, guest I/O counts as progress too. Note that the
96
* offset field is an opaque progress value, it is not a disk offset.
97
*/
98
- job->sectors_read += n;
99
- job->common.offset += n * BDRV_SECTOR_SIZE;
100
+ job->bytes_read += n;
101
+ job->common.offset += n;
102
}
103
104
out:
105
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job)
106
*/
107
if (job->common.speed) {
108
uint64_t delay_ns = ratelimit_calculate_delay(&job->limit,
109
- job->sectors_read *
110
- BDRV_SECTOR_SIZE);
111
- job->sectors_read = 0;
112
+ job->bytes_read);
113
+ job->bytes_read = 0;
114
block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns);
115
} else {
116
block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0);
117
--
118
1.8.3.1
119
120
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
We are gradually converting to byte-based interfaces, as they are
4
easier to reason about than sector-based. Change the internal
5
loop iteration of backups to track by bytes instead of sectors
6
(although we are still guaranteed that we iterate by steps that
7
are cluster-aligned).
8
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Reviewed-by: Jeff Cody <jcody@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/backup.c | 32 +++++++++++++++-----------------
16
1 file changed, 15 insertions(+), 17 deletions(-)
17
18
diff --git a/block/backup.c b/block/backup.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/backup.c
21
+++ b/block/backup.c
22
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
23
int ret = 0;
24
int clusters_per_iter;
25
uint32_t granularity;
26
- int64_t sector;
27
+ int64_t offset;
28
int64_t cluster;
29
int64_t end;
30
int64_t last_cluster = -1;
31
- int64_t sectors_per_cluster = cluster_size_sectors(job);
32
BdrvDirtyBitmapIter *dbi;
33
34
granularity = bdrv_dirty_bitmap_granularity(job->sync_bitmap);
35
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
36
dbi = bdrv_dirty_iter_new(job->sync_bitmap, 0);
37
38
/* Find the next dirty sector(s) */
39
- while ((sector = bdrv_dirty_iter_next(dbi)) != -1) {
40
- cluster = sector / sectors_per_cluster;
41
+ while ((offset = bdrv_dirty_iter_next(dbi) * BDRV_SECTOR_SIZE) >= 0) {
42
+ cluster = offset / job->cluster_size;
43
44
/* Fake progress updates for any clusters we skipped */
45
if (cluster != last_cluster + 1) {
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
47
/* If the bitmap granularity is smaller than the backup granularity,
48
* we need to advance the iterator pointer to the next cluster. */
49
if (granularity < job->cluster_size) {
50
- bdrv_set_dirty_iter(dbi, cluster * sectors_per_cluster);
51
+ bdrv_set_dirty_iter(dbi,
52
+ cluster * job->cluster_size / BDRV_SECTOR_SIZE);
53
}
54
55
last_cluster = cluster - 1;
56
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
57
BackupBlockJob *job = opaque;
58
BackupCompleteData *data;
59
BlockDriverState *bs = blk_bs(job->common.blk);
60
- int64_t start, end;
61
+ int64_t offset;
62
int64_t sectors_per_cluster = cluster_size_sectors(job);
63
int ret = 0;
64
65
QLIST_INIT(&job->inflight_reqs);
66
qemu_co_rwlock_init(&job->flush_rwlock);
67
68
- start = 0;
69
- end = DIV_ROUND_UP(job->common.len, job->cluster_size);
70
-
71
- job->done_bitmap = bitmap_new(end);
72
+ job->done_bitmap = bitmap_new(DIV_ROUND_UP(job->common.len,
73
+ job->cluster_size));
74
75
job->before_write.notify = backup_before_write_notify;
76
bdrv_add_before_write_notifier(bs, &job->before_write);
77
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
78
ret = backup_run_incremental(job);
79
} else {
80
/* Both FULL and TOP SYNC_MODE's require copying.. */
81
- for (; start < end; start++) {
82
+ for (offset = 0; offset < job->common.len;
83
+ offset += job->cluster_size) {
84
bool error_is_read;
85
int alloced = 0;
86
87
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
88
* needed but at some point that is always the case. */
89
alloced =
90
bdrv_is_allocated(bs,
91
- start * sectors_per_cluster + i,
92
- sectors_per_cluster - i, &n);
93
+ (offset >> BDRV_SECTOR_BITS) + i,
94
+ sectors_per_cluster - i, &n);
95
i += n;
96
97
if (alloced || n == 0) {
98
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
99
if (alloced < 0) {
100
ret = alloced;
101
} else {
102
- ret = backup_do_cow(job, start * job->cluster_size,
103
- job->cluster_size, &error_is_read,
104
- false);
105
+ ret = backup_do_cow(job, offset, job->cluster_size,
106
+ &error_is_read, false);
107
}
108
if (ret < 0) {
109
/* Depending on error action, fail now or retry cluster */
110
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
111
if (action == BLOCK_ERROR_ACTION_REPORT) {
112
break;
113
} else {
114
- start--;
115
+ offset -= job->cluster_size;
116
continue;
117
}
118
}
119
--
120
1.8.3.1
121
122
diff view generated by jsdifflib
Deleted patch
1
From: Eric Blake <eblake@redhat.com>
2
1
3
bdrv_is_allocated_above() was relying on intermediate->total_sectors,
4
which is a field that can have stale contents depending on the value
5
of intermediate->has_variable_length. An audit shows that we are safe
6
(we were first calling through bdrv_co_get_block_status() which in
7
turn calls bdrv_nb_sectors() and therefore just refreshed the current
8
length), but it's nicer to favor our accessor functions to avoid having
9
to repeat such an audit, even if it means refresh_total_sectors() is
10
called more frequently.
11
12
Suggested-by: John Snow <jsnow@redhat.com>
13
Signed-off-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
15
Reviewed-by: Jeff Cody <jcody@redhat.com>
16
Reviewed-by: John Snow <jsnow@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/io.c | 14 ++++++--------
20
1 file changed, 6 insertions(+), 8 deletions(-)
21
22
diff --git a/block/io.c b/block/io.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/io.c
25
+++ b/block/io.c
26
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top,
27
intermediate = top;
28
while (intermediate && intermediate != base) {
29
int64_t pnum_inter;
30
+ int64_t size_inter;
31
int psectors_inter;
32
33
ret = bdrv_is_allocated(intermediate, sector_num * BDRV_SECTOR_SIZE,
34
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top,
35
return 1;
36
}
37
38
- /*
39
- * [sector_num, nb_sectors] is unallocated on top but intermediate
40
- * might have
41
- *
42
- * [sector_num+x, nr_sectors] allocated.
43
- */
44
+ size_inter = bdrv_nb_sectors(intermediate);
45
+ if (size_inter < 0) {
46
+ return size_inter;
47
+ }
48
if (n > psectors_inter &&
49
- (intermediate == top ||
50
- sector_num + psectors_inter < intermediate->total_sectors)) {
51
+ (intermediate == top || sector_num + psectors_inter < size_inter)) {
52
n = psectors_inter;
53
}
54
55
--
56
1.8.3.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
When integrating the crypto support with qcow/qcow2, we don't
4
want to use the bare LUKS option names "hash-alg", "key-secret",
5
etc. We need to namespace them to match the nested QAPI schema.
6
7
e.g. "encrypt.hash-alg", "encrypt.key-secret"
8
9
so that they don't clash with any general qcow options at a later
10
date.
11
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
16
Message-id: 20170623162419.26068-3-berrange@redhat.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/crypto.c | 16 ++++++++--------
20
block/crypto.h | 40 ++++++++++++++++++++--------------------
21
2 files changed, 28 insertions(+), 28 deletions(-)
22
23
diff --git a/block/crypto.c b/block/crypto.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/crypto.c
26
+++ b/block/crypto.c
27
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_runtime_opts_luks = {
28
.name = "crypto",
29
.head = QTAILQ_HEAD_INITIALIZER(block_crypto_runtime_opts_luks.head),
30
.desc = {
31
- BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
32
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
33
{ /* end of list */ }
34
},
35
};
36
@@ -XXX,XX +XXX,XX @@ static QemuOptsList block_crypto_create_opts_luks = {
37
.type = QEMU_OPT_SIZE,
38
.help = "Virtual disk size"
39
},
40
- BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET,
41
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG,
42
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE,
43
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG,
44
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG,
45
- BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG,
46
- BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME,
47
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(""),
48
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(""),
49
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(""),
50
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(""),
51
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
52
+ BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
53
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
54
{ /* end of list */ }
55
},
56
};
57
diff --git a/block/crypto.h b/block/crypto.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.h
60
+++ b/block/crypto.h
61
@@ -XXX,XX +XXX,XX @@
62
#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
63
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
64
65
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET \
66
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
67
{ \
68
- .name = BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
69
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
70
.type = QEMU_OPT_STRING, \
71
.help = "ID of the secret that provides the keyslot passphrase", \
72
}
73
74
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG \
75
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(prefix) \
76
{ \
77
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \
78
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG, \
79
.type = QEMU_OPT_STRING, \
80
.help = "Name of encryption cipher algorithm", \
81
}
82
83
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE \
84
- { \
85
- .name = BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \
86
- .type = QEMU_OPT_STRING, \
87
- .help = "Name of encryption cipher mode", \
88
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE(prefix) \
89
+ { \
90
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE, \
91
+ .type = QEMU_OPT_STRING, \
92
+ .help = "Name of encryption cipher mode", \
93
}
94
95
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG \
96
- { \
97
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \
98
- .type = QEMU_OPT_STRING, \
99
- .help = "Name of IV generator algorithm", \
100
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG(prefix) \
101
+ { \
102
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG, \
103
+ .type = QEMU_OPT_STRING, \
104
+ .help = "Name of IV generator algorithm", \
105
}
106
107
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG \
108
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(prefix) \
109
{ \
110
- .name = BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \
111
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG, \
112
.type = QEMU_OPT_STRING, \
113
.help = "Name of IV generator hash algorithm", \
114
}
115
116
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG \
117
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(prefix) \
118
{ \
119
- .name = BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \
120
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_HASH_ALG, \
121
.type = QEMU_OPT_STRING, \
122
.help = "Name of encryption hash algorithm", \
123
}
124
125
-#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME \
126
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(prefix) \
127
{ \
128
- .name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \
129
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_ITER_TIME, \
130
.type = QEMU_OPT_NUMBER, \
131
.help = "Time to spend in PBKDF in milliseconds", \
132
}
133
--
134
1.8.3.1
135
136
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Document that use of guest virtual sector numbers as the basis for
4
the initialization vectors is a potential weakness, when combined
5
with internal snapshots or multiple images using the same passphrase.
6
This fixes the formatting of the itemized list too.
7
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
11
Message-id: 20170623162419.26068-4-berrange@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
qemu-img.texi | 19 ++++++++++++++++---
15
1 file changed, 16 insertions(+), 3 deletions(-)
16
17
diff --git a/qemu-img.texi b/qemu-img.texi
18
index XXXXXXX..XXXXXXX 100644
19
--- a/qemu-img.texi
20
+++ b/qemu-img.texi
21
@@ -XXX,XX +XXX,XX @@ The use of encryption in qcow and qcow2 images is considered to be flawed by
22
modern cryptography standards, suffering from a number of design problems:
23
24
@itemize @minus
25
-@item The AES-CBC cipher is used with predictable initialization vectors based
26
+@item
27
+The AES-CBC cipher is used with predictable initialization vectors based
28
on the sector number. This makes it vulnerable to chosen plaintext attacks
29
which can reveal the existence of encrypted data.
30
-@item The user passphrase is directly used as the encryption key. A poorly
31
+@item
32
+The user passphrase is directly used as the encryption key. A poorly
33
chosen or short passphrase will compromise the security of the encryption.
34
-@item In the event of the passphrase being compromised there is no way to
35
+@item
36
+In the event of the passphrase being compromised there is no way to
37
change the passphrase to protect data in any qcow images. The files must
38
be cloned, using a different encryption passphrase in the new file. The
39
original file must then be securely erased using a program like shred,
40
though even this is ineffective with many modern storage technologies.
41
+@item
42
+Initialization vectors used to encrypt sectors are based on the
43
+guest virtual sector number, instead of the host physical sector. When
44
+a disk image has multiple internal snapshots this means that data in
45
+multiple physical sectors is encrypted with the same initialization
46
+vector. With the CBC mode, this opens the possibility of watermarking
47
+attacks if the attack can collect multiple sectors encrypted with the
48
+same IV and some predictable data. Having multiple qcow2 images with
49
+the same passphrase also exposes this weakness since the passphrase
50
+is directly used as the key.
51
@end itemize
52
53
Use of qcow / qcow2 encryption is thus strongly discouraged. Users are
54
--
55
1.8.3.1
56
57
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
The qcow driver refuses to open images which are less than
4
2 bytes in size, but will happily create such images. Add
5
a check in the create path to avoid this discrepancy.
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
11
Message-id: 20170623162419.26068-5-berrange@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/qcow.c | 6 ++++++
15
1 file changed, 6 insertions(+)
16
17
diff --git a/block/qcow.c b/block/qcow.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow.c
20
+++ b/block/qcow.c
21
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
22
/* Read out options */
23
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
24
BDRV_SECTOR_SIZE);
25
+ if (total_size == 0) {
26
+ error_setg(errp, "Image size is too small, cannot be zero length");
27
+ ret = -EINVAL;
28
+ goto cleanup;
29
+ }
30
+
31
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
32
if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
33
flags |= BLOCK_FLAG_ENCRYPT;
34
--
35
1.8.3.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Test 042 is designed to verify operation with zero sized images.
4
Such images are not supported with qcow (v1), so this test has
5
always failed.
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
10
Message-id: 20170623162419.26068-6-berrange@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/042 | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/tests/qemu-iotests/042 b/tests/qemu-iotests/042
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/042
19
+++ b/tests/qemu-iotests/042
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
21
. ./common.rc
22
. ./common.filter
23
24
-_supported_fmt qcow2 qcow qed
25
+_supported_fmt qcow2 qed
26
_supported_proto file
27
_supported_os Linux
28
29
--
30
1.8.3.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Test 048 is designed to verify data preservation during an
4
image resize. The qcow (v1) format impl has never supported
5
resize so always fails.
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
10
Message-id: 20170623162419.26068-7-berrange@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/048 | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/048
19
+++ b/tests/qemu-iotests/048
20
@@ -XXX,XX +XXX,XX @@ _compare()
21
. ./common.filter
22
. ./common.pattern
23
24
-_supported_fmt raw qcow qcow2 qed luks
25
+_supported_fmt raw qcow2 qed luks
26
_supported_proto file
27
_supported_os Linux
28
29
--
30
1.8.3.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Historically the qcow & qcow2 image formats supported a property
4
"encryption=on" to enable their built-in AES encryption. We'll
5
soon be supporting LUKS for qcow2, so need a more general purpose
6
way to enable encryption, with a choice of formats.
7
8
This introduces an "encrypt.format" option, which will later be
9
joined by a number of other "encrypt.XXX" options. The use of
10
a "encrypt." prefix instead of "encrypt-" is done to facilitate
11
mapping to a nested QAPI schema at later date.
12
13
e.g. the preferred syntax is now
14
15
qemu-img create -f qcow2 -o encrypt.format=aes demo.qcow2
16
17
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
18
Message-id: 20170623162419.26068-8-berrange@redhat.com
19
Reviewed-by: Alberto Garcia <berto@igalia.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block/qcow.c | 31 ++++++++++++---
23
block/qcow2.c | 34 ++++++++++++----
24
include/block/block_int.h | 2 +-
25
qemu-img.c | 4 +-
26
tests/qemu-iotests/049.out | 98 +++++++++++++++++++++++-----------------------
27
tests/qemu-iotests/082.out | 95 ++++++++++++++++++++++++++++----------------
28
tests/qemu-iotests/085.out | 38 +++++++++---------
29
tests/qemu-iotests/144.out | 4 +-
30
tests/qemu-iotests/185.out | 8 ++--
31
9 files changed, 191 insertions(+), 123 deletions(-)
32
33
diff --git a/block/qcow.c b/block/qcow.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block/qcow.c
36
+++ b/block/qcow.c
37
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
38
uint8_t *tmp;
39
int64_t total_size = 0;
40
char *backing_file = NULL;
41
- int flags = 0;
42
Error *local_err = NULL;
43
int ret;
44
BlockBackend *qcow_blk;
45
+ const char *encryptfmt = NULL;
46
47
/* Read out options */
48
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
49
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
50
}
51
52
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
53
- if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
54
- flags |= BLOCK_FLAG_ENCRYPT;
55
+ encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
56
+ if (encryptfmt) {
57
+ if (qemu_opt_get(opts, BLOCK_OPT_ENCRYPT)) {
58
+ error_setg(errp, "Options " BLOCK_OPT_ENCRYPT " and "
59
+ BLOCK_OPT_ENCRYPT_FORMAT " are mutually exclusive");
60
+ ret = -EINVAL;
61
+ goto cleanup;
62
+ }
63
+ } else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
64
+ encryptfmt = "aes";
65
}
66
67
ret = bdrv_create_file(filename, opts, &local_err);
68
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
69
l1_size = (total_size + (1LL << shift) - 1) >> shift;
70
71
header.l1_table_offset = cpu_to_be64(header_size);
72
- if (flags & BLOCK_FLAG_ENCRYPT) {
73
+ if (encryptfmt) {
74
+ if (!g_str_equal(encryptfmt, "aes")) {
75
+ error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
76
+ encryptfmt);
77
+ ret = -EINVAL;
78
+ goto exit;
79
+ }
80
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
81
} else {
82
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
83
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
84
{
85
.name = BLOCK_OPT_ENCRYPT,
86
.type = QEMU_OPT_BOOL,
87
- .help = "Encrypt the image",
88
- .def_value_str = "off"
89
+ .help = "Encrypt the image with format 'aes'. (Deprecated "
90
+ "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",
91
+ },
92
+ {
93
+ .name = BLOCK_OPT_ENCRYPT_FORMAT,
94
+ .type = QEMU_OPT_STRING,
95
+ .help = "Encrypt the image, format choices: 'aes'",
96
},
97
{ /* end of list */ }
98
}
99
diff --git a/block/qcow2.c b/block/qcow2.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/qcow2.c
102
+++ b/block/qcow2.c
103
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
104
const char *backing_file, const char *backing_format,
105
int flags, size_t cluster_size, PreallocMode prealloc,
106
QemuOpts *opts, int version, int refcount_order,
107
- Error **errp)
108
+ const char *encryptfmt, Error **errp)
109
{
110
int cluster_bits;
111
QDict *options;
112
@@ -XXX,XX +XXX,XX @@ static int qcow2_create2(const char *filename, int64_t total_size,
113
.header_length = cpu_to_be32(sizeof(*header)),
114
};
115
116
- if (flags & BLOCK_FLAG_ENCRYPT) {
117
+ if (encryptfmt) {
118
+ if (!g_str_equal(encryptfmt, "aes")) {
119
+ error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
120
+ encryptfmt);
121
+ ret = -EINVAL;
122
+ goto out;
123
+ }
124
header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
125
} else {
126
header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
127
@@ -XXX,XX +XXX,XX @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
128
int version = 3;
129
uint64_t refcount_bits = 16;
130
int refcount_order;
131
+ const char *encryptfmt = NULL;
132
Error *local_err = NULL;
133
int ret;
134
135
@@ -XXX,XX +XXX,XX @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
136
BDRV_SECTOR_SIZE);
137
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
138
backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
139
- if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
140
- flags |= BLOCK_FLAG_ENCRYPT;
141
+ encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
142
+ if (encryptfmt) {
143
+ if (qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT)) {
144
+ error_setg(errp, "Options " BLOCK_OPT_ENCRYPT " and "
145
+ BLOCK_OPT_ENCRYPT_FORMAT " are mutually exclusive");
146
+ ret = -EINVAL;
147
+ goto finish;
148
+ }
149
+ } else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
150
+ encryptfmt = "aes";
151
}
152
cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
153
DEFAULT_CLUSTER_SIZE);
154
@@ -XXX,XX +XXX,XX @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
155
156
ret = qcow2_create2(filename, size, backing_file, backing_fmt, flags,
157
cluster_size, prealloc, opts, version, refcount_order,
158
- &local_err);
159
+ encryptfmt, &local_err);
160
error_propagate(errp, local_err);
161
162
finish:
163
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
164
{
165
.name = BLOCK_OPT_ENCRYPT,
166
.type = QEMU_OPT_BOOL,
167
- .help = "Encrypt the image",
168
- .def_value_str = "off"
169
+ .help = "Encrypt the image with format 'aes'. (Deprecated "
170
+ "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",
171
+ },
172
+ {
173
+ .name = BLOCK_OPT_ENCRYPT_FORMAT,
174
+ .type = QEMU_OPT_STRING,
175
+ .help = "Encrypt the image, format choices: 'aes'",
176
},
177
{
178
.name = BLOCK_OPT_CLUSTER_SIZE,
179
diff --git a/include/block/block_int.h b/include/block/block_int.h
180
index XXXXXXX..XXXXXXX 100644
181
--- a/include/block/block_int.h
182
+++ b/include/block/block_int.h
183
@@ -XXX,XX +XXX,XX @@
184
#include "qemu/main-loop.h"
185
#include "qemu/throttle.h"
186
187
-#define BLOCK_FLAG_ENCRYPT 1
188
#define BLOCK_FLAG_LAZY_REFCOUNTS 8
189
190
#define BLOCK_OPT_SIZE "size"
191
#define BLOCK_OPT_ENCRYPT "encryption"
192
+#define BLOCK_OPT_ENCRYPT_FORMAT "encrypt.format"
193
#define BLOCK_OPT_COMPAT6 "compat6"
194
#define BLOCK_OPT_HWVERSION "hwversion"
195
#define BLOCK_OPT_BACKING_FILE "backing_file"
196
diff --git a/qemu-img.c b/qemu-img.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/qemu-img.c
199
+++ b/qemu-img.c
200
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
201
if (s.compressed) {
202
bool encryption =
203
qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
204
+ const char *encryptfmt =
205
+ qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT);
206
const char *preallocation =
207
qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
208
209
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
210
goto out;
211
}
212
213
- if (encryption) {
214
+ if (encryption || encryptfmt) {
215
error_report("Compression and encryption not supported at "
216
"the same time");
217
ret = -1;
218
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
219
index XXXXXXX..XXXXXXX 100644
220
--- a/tests/qemu-iotests/049.out
221
+++ b/tests/qemu-iotests/049.out
222
@@ -XXX,XX +XXX,XX @@ QA output created by 049
223
== 1. Traditional size parameter ==
224
225
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
226
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
227
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
228
229
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
230
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
231
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
232
233
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
234
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
235
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
236
237
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
238
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
239
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
240
241
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
242
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
243
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16
244
245
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
246
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16
248
249
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
250
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16
252
253
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
254
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
255
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
256
257
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
258
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
259
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
260
261
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
262
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
263
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
264
265
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
266
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
267
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
268
269
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
270
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
271
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
272
273
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
274
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
275
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
277
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
278
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
279
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
281
== 2. Specifying size via -o ==
282
283
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
284
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
285
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
286
287
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
288
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
289
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
290
291
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
292
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
293
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
294
295
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
296
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
297
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
298
299
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
300
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
301
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16
302
303
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
304
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
305
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16
306
307
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
308
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
309
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16
310
311
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
312
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
313
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
315
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
316
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
317
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
318
319
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
320
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
321
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
322
323
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
324
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
325
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
326
327
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
328
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
329
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
330
331
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
332
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16
334
335
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
336
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
337
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16
338
339
== 3. Invalid sizes ==
340
341
@@ -XXX,XX +XXX,XX @@ qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
342
== Check correct interpretation of suffixes for cluster size ==
343
344
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
345
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
346
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
347
348
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
349
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
350
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
351
352
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
353
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
354
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
355
356
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
357
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
358
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
359
360
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
361
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1048576 lazy_refcounts=off refcount_bits=16
362
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16
363
364
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
365
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
366
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
367
368
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
369
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=1024 lazy_refcounts=off refcount_bits=16
370
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
371
372
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
373
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16
374
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16
375
376
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
377
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=512 lazy_refcounts=off refcount_bits=16
378
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16
379
380
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
381
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=524288 lazy_refcounts=off refcount_bits=16
382
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16
383
384
== Check compat level option ==
385
386
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
387
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
388
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16
389
390
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
391
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
392
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
394
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
395
qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42'
396
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
397
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16
398
399
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
400
qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar'
401
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
402
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16
403
404
== Check preallocation option ==
405
406
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
407
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16
408
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16
409
410
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
411
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16
412
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16
413
414
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
415
qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234
416
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16
417
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16
418
419
== Check encryption option ==
420
421
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_siz
422
== Check lazy_refcounts option (only with v3) ==
423
424
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
425
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
426
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16
427
428
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
429
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
430
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16
431
432
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
433
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16
435
436
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
437
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
438
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
439
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16
440
441
*** done
442
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
443
index XXXXXXX..XXXXXXX 100644
444
--- a/tests/qemu-iotests/082.out
445
+++ b/tests/qemu-iotests/082.out
446
@@ -XXX,XX +XXX,XX @@ QA output created by 082
447
=== create: Options specified more than once ===
448
449
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
450
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
451
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
452
image: TEST_DIR/t.IMGFMT
453
file format: IMGFMT
454
virtual size: 128M (134217728 bytes)
455
cluster_size: 65536
456
457
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M
458
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=4096 lazy_refcounts=on refcount_bits=16
459
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16
460
image: TEST_DIR/t.IMGFMT
461
file format: IMGFMT
462
virtual size: 128M (134217728 bytes)
463
@@ -XXX,XX +XXX,XX @@ Format specific information:
464
corrupt: false
465
466
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M
467
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=on refcount_bits=16
468
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16
469
image: TEST_DIR/t.IMGFMT
470
file format: IMGFMT
471
virtual size: 128M (134217728 bytes)
472
@@ -XXX,XX +XXX,XX @@ Format specific information:
473
corrupt: false
474
475
Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M
476
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=8192 lazy_refcounts=off refcount_bits=16
477
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16
478
image: TEST_DIR/t.IMGFMT
479
file format: IMGFMT
480
virtual size: 128M (134217728 bytes)
481
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
482
compat Compatibility level (0.10 or 1.1)
483
backing_file File name of a base image
484
backing_fmt Image format of the base image
485
-encryption Encrypt the image
486
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
487
+encrypt.format Encrypt the image, format choices: 'aes'
488
cluster_size qcow2 cluster size
489
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
490
lazy_refcounts Postpone refcount updates
491
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
492
compat Compatibility level (0.10 or 1.1)
493
backing_file File name of a base image
494
backing_fmt Image format of the base image
495
-encryption Encrypt the image
496
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
497
+encrypt.format Encrypt the image, format choices: 'aes'
498
cluster_size qcow2 cluster size
499
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
500
lazy_refcounts Postpone refcount updates
501
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
502
compat Compatibility level (0.10 or 1.1)
503
backing_file File name of a base image
504
backing_fmt Image format of the base image
505
-encryption Encrypt the image
506
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
507
+encrypt.format Encrypt the image, format choices: 'aes'
508
cluster_size qcow2 cluster size
509
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
510
lazy_refcounts Postpone refcount updates
511
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
512
compat Compatibility level (0.10 or 1.1)
513
backing_file File name of a base image
514
backing_fmt Image format of the base image
515
-encryption Encrypt the image
516
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
517
+encrypt.format Encrypt the image, format choices: 'aes'
518
cluster_size qcow2 cluster size
519
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
520
lazy_refcounts Postpone refcount updates
521
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
522
compat Compatibility level (0.10 or 1.1)
523
backing_file File name of a base image
524
backing_fmt Image format of the base image
525
-encryption Encrypt the image
526
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
527
+encrypt.format Encrypt the image, format choices: 'aes'
528
cluster_size qcow2 cluster size
529
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
530
lazy_refcounts Postpone refcount updates
531
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
532
compat Compatibility level (0.10 or 1.1)
533
backing_file File name of a base image
534
backing_fmt Image format of the base image
535
-encryption Encrypt the image
536
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
537
+encrypt.format Encrypt the image, format choices: 'aes'
538
cluster_size qcow2 cluster size
539
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
540
lazy_refcounts Postpone refcount updates
541
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
542
compat Compatibility level (0.10 or 1.1)
543
backing_file File name of a base image
544
backing_fmt Image format of the base image
545
-encryption Encrypt the image
546
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
547
+encrypt.format Encrypt the image, format choices: 'aes'
548
cluster_size qcow2 cluster size
549
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
550
lazy_refcounts Postpone refcount updates
551
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
552
compat Compatibility level (0.10 or 1.1)
553
backing_file File name of a base image
554
backing_fmt Image format of the base image
555
-encryption Encrypt the image
556
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
557
+encrypt.format Encrypt the image, format choices: 'aes'
558
cluster_size qcow2 cluster size
559
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
560
lazy_refcounts Postpone refcount updates
561
@@ -XXX,XX +XXX,XX @@ refcount_bits Width of a reference count entry in bits
562
nocow Turn off copy-on-write (valid only on btrfs)
563
564
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
565
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
566
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16
567
568
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
569
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
570
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16
571
572
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
573
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
574
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
575
compat Compatibility level (0.10 or 1.1)
576
backing_file File name of a base image
577
backing_fmt Image format of the base image
578
-encryption Encrypt the image
579
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
580
+encrypt.format Encrypt the image, format choices: 'aes'
581
cluster_size qcow2 cluster size
582
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
583
lazy_refcounts Postpone refcount updates
584
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
585
=== convert: Options specified more than once ===
586
587
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
588
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
589
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
590
591
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
592
image: TEST_DIR/t.IMGFMT.base
593
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
594
compat Compatibility level (0.10 or 1.1)
595
backing_file File name of a base image
596
backing_fmt Image format of the base image
597
-encryption Encrypt the image
598
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
599
+encrypt.format Encrypt the image, format choices: 'aes'
600
cluster_size qcow2 cluster size
601
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
602
lazy_refcounts Postpone refcount updates
603
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
604
compat Compatibility level (0.10 or 1.1)
605
backing_file File name of a base image
606
backing_fmt Image format of the base image
607
-encryption Encrypt the image
608
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
609
+encrypt.format Encrypt the image, format choices: 'aes'
610
cluster_size qcow2 cluster size
611
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
612
lazy_refcounts Postpone refcount updates
613
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
614
compat Compatibility level (0.10 or 1.1)
615
backing_file File name of a base image
616
backing_fmt Image format of the base image
617
-encryption Encrypt the image
618
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
619
+encrypt.format Encrypt the image, format choices: 'aes'
620
cluster_size qcow2 cluster size
621
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
622
lazy_refcounts Postpone refcount updates
623
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
624
compat Compatibility level (0.10 or 1.1)
625
backing_file File name of a base image
626
backing_fmt Image format of the base image
627
-encryption Encrypt the image
628
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
629
+encrypt.format Encrypt the image, format choices: 'aes'
630
cluster_size qcow2 cluster size
631
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
632
lazy_refcounts Postpone refcount updates
633
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
634
compat Compatibility level (0.10 or 1.1)
635
backing_file File name of a base image
636
backing_fmt Image format of the base image
637
-encryption Encrypt the image
638
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
639
+encrypt.format Encrypt the image, format choices: 'aes'
640
cluster_size qcow2 cluster size
641
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
642
lazy_refcounts Postpone refcount updates
643
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
644
compat Compatibility level (0.10 or 1.1)
645
backing_file File name of a base image
646
backing_fmt Image format of the base image
647
-encryption Encrypt the image
648
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
649
+encrypt.format Encrypt the image, format choices: 'aes'
650
cluster_size qcow2 cluster size
651
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
652
lazy_refcounts Postpone refcount updates
653
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
654
compat Compatibility level (0.10 or 1.1)
655
backing_file File name of a base image
656
backing_fmt Image format of the base image
657
-encryption Encrypt the image
658
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
659
+encrypt.format Encrypt the image, format choices: 'aes'
660
cluster_size qcow2 cluster size
661
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
662
lazy_refcounts Postpone refcount updates
663
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
664
compat Compatibility level (0.10 or 1.1)
665
backing_file File name of a base image
666
backing_fmt Image format of the base image
667
-encryption Encrypt the image
668
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
669
+encrypt.format Encrypt the image, format choices: 'aes'
670
cluster_size qcow2 cluster size
671
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
672
lazy_refcounts Postpone refcount updates
673
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
674
compat Compatibility level (0.10 or 1.1)
675
backing_file File name of a base image
676
backing_fmt Image format of the base image
677
-encryption Encrypt the image
678
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
679
+encrypt.format Encrypt the image, format choices: 'aes'
680
cluster_size qcow2 cluster size
681
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
682
lazy_refcounts Postpone refcount updates
683
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
684
compat Compatibility level (0.10 or 1.1)
685
backing_file File name of a base image
686
backing_fmt Image format of the base image
687
-encryption Encrypt the image
688
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
689
+encrypt.format Encrypt the image, format choices: 'aes'
690
cluster_size qcow2 cluster size
691
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
692
lazy_refcounts Postpone refcount updates
693
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
694
compat Compatibility level (0.10 or 1.1)
695
backing_file File name of a base image
696
backing_fmt Image format of the base image
697
-encryption Encrypt the image
698
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
699
+encrypt.format Encrypt the image, format choices: 'aes'
700
cluster_size qcow2 cluster size
701
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
702
lazy_refcounts Postpone refcount updates
703
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
704
compat Compatibility level (0.10 or 1.1)
705
backing_file File name of a base image
706
backing_fmt Image format of the base image
707
-encryption Encrypt the image
708
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
709
+encrypt.format Encrypt the image, format choices: 'aes'
710
cluster_size qcow2 cluster size
711
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
712
lazy_refcounts Postpone refcount updates
713
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
714
compat Compatibility level (0.10 or 1.1)
715
backing_file File name of a base image
716
backing_fmt Image format of the base image
717
-encryption Encrypt the image
718
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
719
+encrypt.format Encrypt the image, format choices: 'aes'
720
cluster_size qcow2 cluster size
721
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
722
lazy_refcounts Postpone refcount updates
723
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
724
compat Compatibility level (0.10 or 1.1)
725
backing_file File name of a base image
726
backing_fmt Image format of the base image
727
-encryption Encrypt the image
728
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
729
+encrypt.format Encrypt the image, format choices: 'aes'
730
cluster_size qcow2 cluster size
731
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
732
lazy_refcounts Postpone refcount updates
733
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
734
compat Compatibility level (0.10 or 1.1)
735
backing_file File name of a base image
736
backing_fmt Image format of the base image
737
-encryption Encrypt the image
738
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
739
+encrypt.format Encrypt the image, format choices: 'aes'
740
cluster_size qcow2 cluster size
741
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
742
lazy_refcounts Postpone refcount updates
743
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
744
compat Compatibility level (0.10 or 1.1)
745
backing_file File name of a base image
746
backing_fmt Image format of the base image
747
-encryption Encrypt the image
748
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
749
+encrypt.format Encrypt the image, format choices: 'aes'
750
cluster_size qcow2 cluster size
751
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
752
lazy_refcounts Postpone refcount updates
753
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
754
compat Compatibility level (0.10 or 1.1)
755
backing_file File name of a base image
756
backing_fmt Image format of the base image
757
-encryption Encrypt the image
758
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
759
+encrypt.format Encrypt the image, format choices: 'aes'
760
cluster_size qcow2 cluster size
761
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
762
lazy_refcounts Postpone refcount updates
763
@@ -XXX,XX +XXX,XX @@ size Virtual disk size
764
compat Compatibility level (0.10 or 1.1)
765
backing_file File name of a base image
766
backing_fmt Image format of the base image
767
-encryption Encrypt the image
768
+encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
769
+encrypt.format Encrypt the image, format choices: 'aes'
770
cluster_size qcow2 cluster size
771
preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
772
lazy_refcounts Postpone refcount updates
773
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
774
index XXXXXXX..XXXXXXX 100644
775
--- a/tests/qemu-iotests/085.out
776
+++ b/tests/qemu-iotests/085.out
777
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
778
779
=== Create a single snapshot on virtio0 ===
780
781
-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
782
+Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
783
{"return": {}}
784
785
=== Invalid command - missing device and nodename ===
786
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file
787
788
=== Create several transactional group snapshots ===
789
790
-Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
791
-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
792
+Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
793
+Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
794
{"return": {}}
795
-Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
796
-Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
797
+Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
798
+Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
799
{"return": {}}
800
-Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
801
-Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
802
+Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
803
+Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
804
{"return": {}}
805
-Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
806
-Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
807
+Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
808
+Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
809
{"return": {}}
810
-Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
811
-Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
812
+Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
813
+Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
814
{"return": {}}
815
-Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
816
-Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
817
+Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
818
+Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
819
{"return": {}}
820
-Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
821
-Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
822
+Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
823
+Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
824
{"return": {}}
825
-Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
826
-Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
827
+Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
828
+Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
829
{"return": {}}
830
-Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
831
-Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
832
+Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
833
+Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
834
{"return": {}}
835
836
=== Create a couple of snapshots using blockdev-snapshot ===
837
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
838
index XXXXXXX..XXXXXXX 100644
839
--- a/tests/qemu-iotests/144.out
840
+++ b/tests/qemu-iotests/144.out
841
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
842
=== Performing Live Snapshot 1 ===
843
844
{"return": {}}
845
-Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
846
+Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
847
{"return": {}}
848
849
=== Performing block-commit on active layer ===
850
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/
851
852
=== Performing Live Snapshot 2 ===
853
854
-Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
855
+Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
856
{"return": {}}
857
*** done
858
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
859
index XXXXXXX..XXXXXXX 100644
860
--- a/tests/qemu-iotests/185.out
861
+++ b/tests/qemu-iotests/185.out
862
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
863
864
=== Creating backing chain ===
865
866
-Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
867
+Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
868
{"return": {}}
869
wrote 4194304/4194304 bytes at offset 0
870
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
871
{"return": ""}
872
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
873
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
874
{"return": {}}
875
876
=== Start commit job and exit qemu ===
877
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q
878
=== Start mirror job and exit qemu ===
879
880
{"return": {}}
881
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
882
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
883
{"return": {}}
884
{"return": {}}
885
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
886
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off clust
887
=== Start backup job and exit qemu ===
888
889
{"return": {}}
890
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
891
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
892
{"return": {}}
893
{"return": {}}
894
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
895
--
896
1.8.3.1
897
898
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Instead of requiring separate input/output buffers for
4
encrypting data, change encrypt_sectors() to assume
5
use of a single buffer, encrypting in place. One current
6
caller uses the same buffer for input/output already
7
and the other two callers are easily converted to do so.
8
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
14
Message-id: 20170623162419.26068-9-berrange@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/qcow.c | 45 +++++++++++++++------------------------------
18
1 file changed, 15 insertions(+), 30 deletions(-)
19
20
diff --git a/block/qcow.c b/block/qcow.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow.c
23
+++ b/block/qcow.c
24
@@ -XXX,XX +XXX,XX @@ static int qcow_set_key(BlockDriverState *bs, const char *key)
25
}
26
27
/* The crypt function is compatible with the linux cryptoloop
28
- algorithm for < 4 GB images. NOTE: out_buf == in_buf is
29
- supported */
30
+ algorithm for < 4 GB images. */
31
static int encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
32
- uint8_t *out_buf, const uint8_t *in_buf,
33
- int nb_sectors, bool enc, Error **errp)
34
+ uint8_t *buf, int nb_sectors, bool enc,
35
+ Error **errp)
36
{
37
union {
38
uint64_t ll[2];
39
@@ -XXX,XX +XXX,XX @@ static int encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
40
}
41
if (enc) {
42
ret = qcrypto_cipher_encrypt(s->cipher,
43
- in_buf,
44
- out_buf,
45
+ buf, buf,
46
512,
47
errp);
48
} else {
49
ret = qcrypto_cipher_decrypt(s->cipher,
50
- in_buf,
51
- out_buf,
52
+ buf, buf,
53
512,
54
errp);
55
}
56
@@ -XXX,XX +XXX,XX @@ static int encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
57
return -1;
58
}
59
sector_num++;
60
- in_buf += 512;
61
- out_buf += 512;
62
+ buf += 512;
63
}
64
return 0;
65
}
66
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
67
uint64_t start_sect;
68
assert(s->cipher);
69
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
70
- memset(s->cluster_data + 512, 0x00, 512);
71
for(i = 0; i < s->cluster_sectors; i++) {
72
if (i < n_start || i >= n_end) {
73
Error *err = NULL;
74
+ memset(s->cluster_data, 0x00, 512);
75
if (encrypt_sectors(s, start_sect + i,
76
- s->cluster_data,
77
- s->cluster_data + 512, 1,
78
+ s->cluster_data, 1,
79
true, &err) < 0) {
80
error_free(err);
81
errno = EIO;
82
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
83
}
84
if (bs->encrypted) {
85
assert(s->cipher);
86
- if (encrypt_sectors(s, sector_num, buf, buf,
87
+ if (encrypt_sectors(s, sector_num, buf,
88
n, false, &err) < 0) {
89
goto fail;
90
}
91
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
92
BDRVQcowState *s = bs->opaque;
93
int index_in_cluster;
94
uint64_t cluster_offset;
95
- const uint8_t *src_buf;
96
int ret = 0, n;
97
- uint8_t *cluster_data = NULL;
98
struct iovec hd_iov;
99
QEMUIOVector hd_qiov;
100
uint8_t *buf;
101
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
102
103
s->cluster_cache_offset = -1; /* disable compressed cache */
104
105
- if (qiov->niov > 1) {
106
+ /* We must always copy the iov when encrypting, so we
107
+ * don't modify the original data buffer during encryption */
108
+ if (bs->encrypted || qiov->niov > 1) {
109
buf = orig_buf = qemu_try_blockalign(bs, qiov->size);
110
if (buf == NULL) {
111
return -ENOMEM;
112
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
113
if (bs->encrypted) {
114
Error *err = NULL;
115
assert(s->cipher);
116
- if (!cluster_data) {
117
- cluster_data = g_malloc0(s->cluster_size);
118
- }
119
- if (encrypt_sectors(s, sector_num, cluster_data, buf,
120
- n, true, &err) < 0) {
121
+ if (encrypt_sectors(s, sector_num, buf, n, true, &err) < 0) {
122
error_free(err);
123
ret = -EIO;
124
break;
125
}
126
- src_buf = cluster_data;
127
- } else {
128
- src_buf = buf;
129
}
130
131
- hd_iov.iov_base = (void *)src_buf;
132
+ hd_iov.iov_base = (void *)buf;
133
hd_iov.iov_len = n * 512;
134
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
135
qemu_co_mutex_unlock(&s->lock);
136
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
137
}
138
qemu_co_mutex_unlock(&s->lock);
139
140
- if (qiov->niov > 1) {
141
- qemu_vfree(orig_buf);
142
- }
143
- g_free(cluster_data);
144
+ qemu_vfree(orig_buf);
145
146
return ret;
147
}
148
--
149
1.8.3.1
150
151
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
This converts the qcow driver to make use of the QCryptoBlock
4
APIs for encrypting image content. This is only wired up to
5
permit use of the legacy QCow encryption format. Users who wish
6
to have the strong LUKS format should switch to qcow2 instead.
7
8
With this change it is now required to use the QCryptoSecret
9
object for providing passwords, instead of the current block
10
password APIs / interactive prompting.
11
12
$QEMU \
13
-object secret,id=sec0,file=/home/berrange/encrypted.pw \
14
-drive file=/home/berrange/encrypted.qcow,encrypt.format=aes,\
15
encrypt.key-secret=sec0
16
17
Though note that running QEMU system emulators with the AES
18
encryption is no longer supported, so while the above syntax
19
is valid, QEMU will refuse to actually run the VM in this
20
particular example.
21
22
Likewise when creating images with the legacy AES-CBC format
23
24
qemu-img create -f qcow \
25
--object secret,id=sec0,file=/home/berrange/encrypted.pw \
26
-o encrypt.format=aes,encrypt.key-secret=sec0 \
27
/home/berrange/encrypted.qcow 64M
28
29
Reviewed-by: Max Reitz <mreitz@redhat.com>
30
Reviewed-by: Alberto Garcia <berto@igalia.com>
31
Reviewed-by: Eric Blake <eblake@redhat.com>
32
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
33
Message-id: 20170623162419.26068-10-berrange@redhat.com
34
Signed-off-by: Max Reitz <mreitz@redhat.com>
35
---
36
block/crypto.c | 10 +++
37
block/crypto.h | 20 ++++--
38
block/qcow.c | 198 +++++++++++++++++++++++++--------------------------
39
qapi/block-core.json | 38 +++++++++-
40
4 files changed, 158 insertions(+), 108 deletions(-)
41
42
diff --git a/block/crypto.c b/block/crypto.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/block/crypto.c
45
+++ b/block/crypto.c
46
@@ -XXX,XX +XXX,XX @@ block_crypto_open_opts_init(QCryptoBlockFormat format,
47
v, &ret->u.luks, &local_err);
48
break;
49
50
+ case Q_CRYPTO_BLOCK_FORMAT_QCOW:
51
+ visit_type_QCryptoBlockOptionsQCow_members(
52
+ v, &ret->u.qcow, &local_err);
53
+ break;
54
+
55
default:
56
error_setg(&local_err, "Unsupported block format %d", format);
57
break;
58
@@ -XXX,XX +XXX,XX @@ block_crypto_create_opts_init(QCryptoBlockFormat format,
59
v, &ret->u.luks, &local_err);
60
break;
61
62
+ case Q_CRYPTO_BLOCK_FORMAT_QCOW:
63
+ visit_type_QCryptoBlockOptionsQCow_members(
64
+ v, &ret->u.qcow, &local_err);
65
+ break;
66
+
67
default:
68
error_setg(&local_err, "Unsupported block format %d", format);
69
break;
70
diff --git a/block/crypto.h b/block/crypto.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/crypto.h
73
+++ b/block/crypto.h
74
@@ -XXX,XX +XXX,XX @@
75
#ifndef BLOCK_CRYPTO_H__
76
#define BLOCK_CRYPTO_H__
77
78
+#define BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, helpstr) \
79
+ { \
80
+ .name = prefix BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET, \
81
+ .type = QEMU_OPT_STRING, \
82
+ .help = helpstr, \
83
+ }
84
+
85
+#define BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET "key-secret"
86
+
87
+#define BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET(prefix) \
88
+ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
89
+ "ID of the secret that provides the AES encryption key")
90
+
91
#define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
92
#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
93
#define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
94
@@ -XXX,XX +XXX,XX @@
95
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
96
97
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
98
- { \
99
- .name = prefix BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET, \
100
- .type = QEMU_OPT_STRING, \
101
- .help = "ID of the secret that provides the keyslot passphrase", \
102
- }
103
+ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
104
+ "ID of the secret that provides the keyslot passphrase")
105
106
#define BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG(prefix) \
107
{ \
108
diff --git a/block/qcow.c b/block/qcow.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/block/qcow.c
111
+++ b/block/qcow.c
112
@@ -XXX,XX +XXX,XX @@
113
#include "qemu/bswap.h"
114
#include <zlib.h>
115
#include "qapi/qmp/qerror.h"
116
-#include "crypto/cipher.h"
117
+#include "qapi/qmp/qstring.h"
118
+#include "crypto/block.h"
119
#include "migration/blocker.h"
120
+#include "block/crypto.h"
121
122
/**************************************************************/
123
/* QEMU COW block driver with compression and encryption support */
124
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
125
uint8_t *cluster_cache;
126
uint8_t *cluster_data;
127
uint64_t cluster_cache_offset;
128
- QCryptoCipher *cipher; /* NULL if no key yet */
129
+ QCryptoBlock *crypto; /* Disk encryption format driver */
130
uint32_t crypt_method_header;
131
CoMutex lock;
132
Error *migration_blocker;
133
@@ -XXX,XX +XXX,XX @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
134
return 0;
135
}
136
137
+static QemuOptsList qcow_runtime_opts = {
138
+ .name = "qcow",
139
+ .head = QTAILQ_HEAD_INITIALIZER(qcow_runtime_opts.head),
140
+ .desc = {
141
+ BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
142
+ { /* end of list */ }
143
+ },
144
+};
145
+
146
static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
147
Error **errp)
148
{
149
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
150
int ret;
151
QCowHeader header;
152
Error *local_err = NULL;
153
+ QCryptoBlockOpenOptions *crypto_opts = NULL;
154
+ unsigned int cflags = 0;
155
+ QDict *encryptopts = NULL;
156
+ const char *encryptfmt;
157
+
158
+ qdict_extract_subqdict(options, &encryptopts, "encrypt.");
159
+ encryptfmt = qdict_get_try_str(encryptopts, "format");
160
161
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
162
false, errp);
163
if (!bs->file) {
164
- return -EINVAL;
165
+ ret = -EINVAL;
166
+ goto fail;
167
}
168
169
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
170
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
171
goto fail;
172
}
173
174
- if (header.crypt_method > QCOW_CRYPT_AES) {
175
- error_setg(errp, "invalid encryption method in qcow header");
176
- ret = -EINVAL;
177
- goto fail;
178
- }
179
- if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128,
180
- QCRYPTO_CIPHER_MODE_CBC)) {
181
- error_setg(errp, "AES cipher not available");
182
- ret = -EINVAL;
183
- goto fail;
184
- }
185
s->crypt_method_header = header.crypt_method;
186
if (s->crypt_method_header) {
187
if (bdrv_uses_whitelist() &&
188
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
189
ret = -ENOSYS;
190
goto fail;
191
}
192
+ if (s->crypt_method_header == QCOW_CRYPT_AES) {
193
+ if (encryptfmt && !g_str_equal(encryptfmt, "aes")) {
194
+ error_setg(errp,
195
+ "Header reported 'aes' encryption format but "
196
+ "options specify '%s'", encryptfmt);
197
+ ret = -EINVAL;
198
+ goto fail;
199
+ }
200
+ qdict_del(encryptopts, "format");
201
+ crypto_opts = block_crypto_open_opts_init(
202
+ Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
203
+ if (!crypto_opts) {
204
+ ret = -EINVAL;
205
+ goto fail;
206
+ }
207
208
+ if (flags & BDRV_O_NO_IO) {
209
+ cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
210
+ }
211
+ s->crypto = qcrypto_block_open(crypto_opts, NULL, NULL,
212
+ cflags, errp);
213
+ if (!s->crypto) {
214
+ ret = -EINVAL;
215
+ goto fail;
216
+ }
217
+ } else {
218
+ error_setg(errp, "invalid encryption method in qcow header");
219
+ ret = -EINVAL;
220
+ goto fail;
221
+ }
222
bs->encrypted = true;
223
+ bs->valid_key = true;
224
}
225
s->cluster_bits = header.cluster_bits;
226
s->cluster_size = 1 << s->cluster_bits;
227
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
228
goto fail;
229
}
230
231
+ QDECREF(encryptopts);
232
+ qapi_free_QCryptoBlockOpenOptions(crypto_opts);
233
qemu_co_mutex_init(&s->lock);
234
return 0;
235
236
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
237
qemu_vfree(s->l2_cache);
238
g_free(s->cluster_cache);
239
g_free(s->cluster_data);
240
+ qcrypto_block_free(s->crypto);
241
+ QDECREF(encryptopts);
242
+ qapi_free_QCryptoBlockOpenOptions(crypto_opts);
243
return ret;
244
}
245
246
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
247
return 0;
248
}
249
250
-static int qcow_set_key(BlockDriverState *bs, const char *key)
251
-{
252
- BDRVQcowState *s = bs->opaque;
253
- uint8_t keybuf[16];
254
- int len, i;
255
- Error *err;
256
-
257
- memset(keybuf, 0, 16);
258
- len = strlen(key);
259
- if (len > 16)
260
- len = 16;
261
- /* XXX: we could compress the chars to 7 bits to increase
262
- entropy */
263
- for(i = 0;i < len;i++) {
264
- keybuf[i] = key[i];
265
- }
266
- assert(bs->encrypted);
267
-
268
- qcrypto_cipher_free(s->cipher);
269
- s->cipher = qcrypto_cipher_new(
270
- QCRYPTO_CIPHER_ALG_AES_128,
271
- QCRYPTO_CIPHER_MODE_CBC,
272
- keybuf, G_N_ELEMENTS(keybuf),
273
- &err);
274
-
275
- if (!s->cipher) {
276
- /* XXX would be nice if errors in this method could
277
- * be properly propagate to the caller. Would need
278
- * the bdrv_set_key() API signature to be fixed. */
279
- error_free(err);
280
- return -1;
281
- }
282
- return 0;
283
-}
284
-
285
-/* The crypt function is compatible with the linux cryptoloop
286
- algorithm for < 4 GB images. */
287
-static int encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
288
- uint8_t *buf, int nb_sectors, bool enc,
289
- Error **errp)
290
-{
291
- union {
292
- uint64_t ll[2];
293
- uint8_t b[16];
294
- } ivec;
295
- int i;
296
- int ret;
297
-
298
- for(i = 0; i < nb_sectors; i++) {
299
- ivec.ll[0] = cpu_to_le64(sector_num);
300
- ivec.ll[1] = 0;
301
- if (qcrypto_cipher_setiv(s->cipher,
302
- ivec.b, G_N_ELEMENTS(ivec.b),
303
- errp) < 0) {
304
- return -1;
305
- }
306
- if (enc) {
307
- ret = qcrypto_cipher_encrypt(s->cipher,
308
- buf, buf,
309
- 512,
310
- errp);
311
- } else {
312
- ret = qcrypto_cipher_decrypt(s->cipher,
313
- buf, buf,
314
- 512,
315
- errp);
316
- }
317
- if (ret < 0) {
318
- return -1;
319
- }
320
- sector_num++;
321
- buf += 512;
322
- }
323
- return 0;
324
-}
325
326
/* 'allocate' is:
327
*
328
@@ -XXX,XX +XXX,XX @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
329
if (bs->encrypted &&
330
(n_end - n_start) < s->cluster_sectors) {
331
uint64_t start_sect;
332
- assert(s->cipher);
333
+ assert(s->crypto);
334
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
335
for(i = 0; i < s->cluster_sectors; i++) {
336
if (i < n_start || i >= n_end) {
337
Error *err = NULL;
338
memset(s->cluster_data, 0x00, 512);
339
- if (encrypt_sectors(s, start_sect + i,
340
- s->cluster_data, 1,
341
- true, &err) < 0) {
342
+ if (qcrypto_block_encrypt(s->crypto, start_sect + i,
343
+ s->cluster_data,
344
+ BDRV_SECTOR_SIZE,
345
+ &err) < 0) {
346
error_free(err);
347
errno = EIO;
348
return -1;
349
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs,
350
if (!cluster_offset) {
351
return 0;
352
}
353
- if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->cipher) {
354
+ if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypto) {
355
return BDRV_BLOCK_DATA;
356
}
357
cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
358
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
359
break;
360
}
361
if (bs->encrypted) {
362
- assert(s->cipher);
363
- if (encrypt_sectors(s, sector_num, buf,
364
- n, false, &err) < 0) {
365
+ assert(s->crypto);
366
+ if (qcrypto_block_decrypt(s->crypto, sector_num, buf,
367
+ n * BDRV_SECTOR_SIZE, &err) < 0) {
368
goto fail;
369
}
370
}
371
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
372
}
373
if (bs->encrypted) {
374
Error *err = NULL;
375
- assert(s->cipher);
376
- if (encrypt_sectors(s, sector_num, buf, n, true, &err) < 0) {
377
+ assert(s->crypto);
378
+ if (qcrypto_block_encrypt(s->crypto, sector_num, buf,
379
+ n * BDRV_SECTOR_SIZE, &err) < 0) {
380
error_free(err);
381
ret = -EIO;
382
break;
383
@@ -XXX,XX +XXX,XX @@ static void qcow_close(BlockDriverState *bs)
384
{
385
BDRVQcowState *s = bs->opaque;
386
387
- qcrypto_cipher_free(s->cipher);
388
- s->cipher = NULL;
389
+ qcrypto_block_free(s->crypto);
390
+ s->crypto = NULL;
391
g_free(s->l1_table);
392
qemu_vfree(s->l2_cache);
393
g_free(s->cluster_cache);
394
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
395
int ret;
396
BlockBackend *qcow_blk;
397
const char *encryptfmt = NULL;
398
+ QDict *options;
399
+ QDict *encryptopts = NULL;
400
+ QCryptoBlockCreateOptions *crypto_opts = NULL;
401
+ QCryptoBlock *crypto = NULL;
402
403
/* Read out options */
404
total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
405
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
406
l1_size = (total_size + (1LL << shift) - 1) >> shift;
407
408
header.l1_table_offset = cpu_to_be64(header_size);
409
+
410
+ options = qemu_opts_to_qdict(opts, NULL);
411
+ qdict_extract_subqdict(options, &encryptopts, "encrypt.");
412
+ QDECREF(options);
413
if (encryptfmt) {
414
if (!g_str_equal(encryptfmt, "aes")) {
415
error_setg(errp, "Unknown encryption format '%s', expected 'aes'",
416
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
417
goto exit;
418
}
419
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
420
+
421
+ crypto_opts = block_crypto_create_opts_init(
422
+ Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
423
+ if (!crypto_opts) {
424
+ ret = -EINVAL;
425
+ goto exit;
426
+ }
427
+
428
+ crypto = qcrypto_block_create(crypto_opts, NULL, NULL, NULL, errp);
429
+ if (!crypto) {
430
+ ret = -EINVAL;
431
+ goto exit;
432
+ }
433
} else {
434
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
435
}
436
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
437
exit:
438
blk_unref(qcow_blk);
439
cleanup:
440
+ QDECREF(encryptopts);
441
+ qcrypto_block_free(crypto);
442
+ qapi_free_QCryptoBlockCreateOptions(crypto_opts);
443
g_free(backing_file);
444
return ret;
445
}
446
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
447
.type = QEMU_OPT_STRING,
448
.help = "Encrypt the image, format choices: 'aes'",
449
},
450
+ BLOCK_CRYPTO_OPT_DEF_QCOW_KEY_SECRET("encrypt."),
451
{ /* end of list */ }
452
}
453
};
454
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
455
.bdrv_co_writev = qcow_co_writev,
456
.bdrv_co_get_block_status = qcow_co_get_block_status,
457
458
- .bdrv_set_key = qcow_set_key,
459
.bdrv_make_empty = qcow_make_empty,
460
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
461
.bdrv_get_info = qcow_get_info,
462
diff --git a/qapi/block-core.json b/qapi/block-core.json
463
index XXXXXXX..XXXXXXX 100644
464
--- a/qapi/block-core.json
465
+++ b/qapi/block-core.json
466
@@ -XXX,XX +XXX,XX @@
467
'mode': 'Qcow2OverlapCheckMode' } }
468
469
##
470
+# @BlockdevQcowEncryptionFormat:
471
+#
472
+# @aes: AES-CBC with plain64 initialization vectors
473
+#
474
+# Since: 2.10
475
+##
476
+{ 'enum': 'BlockdevQcowEncryptionFormat',
477
+ 'data': [ 'aes' ] }
478
+
479
+##
480
+# @BlockdevQcowEncryption:
481
+#
482
+# Since: 2.10
483
+##
484
+{ 'union': 'BlockdevQcowEncryption',
485
+ 'base': { 'format': 'BlockdevQcowEncryptionFormat' },
486
+ 'discriminator': 'format',
487
+ 'data': { 'aes': 'QCryptoBlockOptionsQCow' } }
488
+
489
+##
490
+# @BlockdevOptionsQcow:
491
+#
492
+# Driver specific block device options for qcow.
493
+#
494
+# @encrypt: Image decryption options. Mandatory for
495
+# encrypted images, except when doing a metadata-only
496
+# probe of the image.
497
+#
498
+# Since: 2.10
499
+##
500
+{ 'struct': 'BlockdevOptionsQcow',
501
+ 'base': 'BlockdevOptionsGenericCOWFormat',
502
+ 'data': { '*encrypt': 'BlockdevQcowEncryption' } }
503
+
504
+
505
+##
506
# @BlockdevOptionsQcow2:
507
#
508
# Driver specific block device options for qcow2.
509
@@ -XXX,XX +XXX,XX @@
510
'null-co': 'BlockdevOptionsNull',
511
'parallels': 'BlockdevOptionsGenericFormat',
512
'qcow2': 'BlockdevOptionsQcow2',
513
- 'qcow': 'BlockdevOptionsGenericCOWFormat',
514
+ 'qcow': 'BlockdevOptionsQcow',
515
'qed': 'BlockdevOptionsGenericCOWFormat',
516
'quorum': 'BlockdevOptionsQuorum',
517
'raw': 'BlockdevOptionsRaw',
518
--
519
1.8.3.1
520
521
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Instead of requiring separate input/output buffers for
4
encrypting data, change qcow2_encrypt_sectors() to assume
5
use of a single buffer, encrypting in place. The current
6
callers all used the same buffer for input/output already.
7
8
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
Message-id: 20170623162419.26068-11-berrange@redhat.com
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2-cluster.c | 17 ++++++-----------
14
block/qcow2.c | 4 ++--
15
block/qcow2.h | 3 +--
16
3 files changed, 9 insertions(+), 15 deletions(-)
17
18
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2-cluster.c
21
+++ b/block/qcow2-cluster.c
22
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters_unallocated(int nb_clusters,
23
}
24
25
/* The crypt function is compatible with the linux cryptoloop
26
- algorithm for < 4 GB images. NOTE: out_buf == in_buf is
27
- supported */
28
+ algorithm for < 4 GB images. */
29
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
30
- uint8_t *out_buf, const uint8_t *in_buf,
31
- int nb_sectors, bool enc,
32
+ uint8_t *buf, int nb_sectors, bool enc,
33
Error **errp)
34
{
35
union {
36
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
37
}
38
if (enc) {
39
ret = qcrypto_cipher_encrypt(s->cipher,
40
- in_buf,
41
- out_buf,
42
+ buf, buf,
43
512,
44
errp);
45
} else {
46
ret = qcrypto_cipher_decrypt(s->cipher,
47
- in_buf,
48
- out_buf,
49
+ buf, buf,
50
512,
51
errp);
52
}
53
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
54
return -1;
55
}
56
sector_num++;
57
- in_buf += 512;
58
- out_buf += 512;
59
+ buf += 512;
60
}
61
return 0;
62
}
63
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
64
assert(s->cipher);
65
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
66
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
67
- if (qcow2_encrypt_sectors(s, sector, buffer, buffer,
68
+ if (qcow2_encrypt_sectors(s, sector, buffer,
69
bytes >> BDRV_SECTOR_BITS, true, NULL) < 0) {
70
return false;
71
}
72
diff --git a/block/qcow2.c b/block/qcow2.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/qcow2.c
75
+++ b/block/qcow2.c
76
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
77
assert((cur_bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
78
Error *err = NULL;
79
if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS,
80
- cluster_data, cluster_data,
81
+ cluster_data,
82
cur_bytes >> BDRV_SECTOR_BITS,
83
false, &err) < 0) {
84
error_free(err);
85
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
86
qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
87
88
if (qcow2_encrypt_sectors(s, offset >> BDRV_SECTOR_BITS,
89
- cluster_data, cluster_data,
90
+ cluster_data,
91
cur_bytes >>BDRV_SECTOR_BITS,
92
true, &err) < 0) {
93
error_free(err);
94
diff --git a/block/qcow2.h b/block/qcow2.h
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/qcow2.h
97
+++ b/block/qcow2.h
98
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
99
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
100
int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
101
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
102
- uint8_t *out_buf, const uint8_t *in_buf,
103
- int nb_sectors, bool enc, Error **errp);
104
+ uint8_t *buf, int nb_sectors, bool enc, Error **errp);
105
106
int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
107
unsigned int *bytes, uint64_t *cluster_offset);
108
--
109
1.8.3.1
110
111
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Update the qcow2 specification to describe how the LUKS header is
4
placed inside a qcow2 file, when using LUKS encryption for the
5
qcow2 payload instead of the legacy AES-CBC encryption
6
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
11
Message-id: 20170623162419.26068-13-berrange@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
docs/interop/qcow2.txt | 103 +++++++++++++++++++++++++++++++++++++++++++++++++
15
1 file changed, 103 insertions(+)
16
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
20
+++ b/docs/interop/qcow2.txt
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
22
32 - 35: crypt_method
23
0 for no encryption
24
1 for AES encryption
25
+ 2 for LUKS encryption
26
27
36 - 39: l1_size
28
Number of entries in the active L1 table
29
@@ -XXX,XX +XXX,XX @@ be stored. Each extension has a structure like the following:
30
0xE2792ACA - Backing file format name
31
0x6803f857 - Feature name table
32
0x23852875 - Bitmaps extension
33
+ 0x0537be77 - Full disk encryption header pointer
34
other - Unknown header extension, can be safely
35
ignored
36
37
@@ -XXX,XX +XXX,XX @@ The fields of the bitmaps extension are:
38
Offset into the image file at which the bitmap directory
39
starts. Must be aligned to a cluster boundary.
40
41
+== Full disk encryption header pointer ==
42
+
43
+The full disk encryption header must be present if, and only if, the
44
+'crypt_method' header requires metadata. Currently this is only true
45
+of the 'LUKS' crypt method. The header extension must be absent for
46
+other methods.
47
+
48
+This header provides the offset at which the crypt method can store
49
+its additional data, as well as the length of such data.
50
+
51
+ Byte 0 - 7: Offset into the image file at which the encryption
52
+ header starts in bytes. Must be aligned to a cluster
53
+ boundary.
54
+ Byte 8 - 15: Length of the written encryption header in bytes.
55
+ Note actual space allocated in the qcow2 file may
56
+ be larger than this value, since it will be rounded
57
+ to the nearest multiple of the cluster size. Any
58
+ unused bytes in the allocated space will be initialized
59
+ to 0.
60
+
61
+For the LUKS crypt method, the encryption header works as follows.
62
+
63
+The first 592 bytes of the header clusters will contain the LUKS
64
+partition header. This is then followed by the key material data areas.
65
+The size of the key material data areas is determined by the number of
66
+stripes in the key slot and key size. Refer to the LUKS format
67
+specification ('docs/on-disk-format.pdf' in the cryptsetup source
68
+package) for details of the LUKS partition header format.
69
+
70
+In the LUKS partition header, the "payload-offset" field will be
71
+calculated as normal for the LUKS spec. ie the size of the LUKS
72
+header, plus key material regions, plus padding, relative to the
73
+start of the LUKS header. This offset value is not required to be
74
+qcow2 cluster aligned. Its value is currently never used in the
75
+context of qcow2, since the qcow2 file format itself defines where
76
+the real payload offset is, but none the less a valid payload offset
77
+should always be present.
78
+
79
+In the LUKS key slots header, the "key-material-offset" is relative
80
+to the start of the LUKS header clusters in the qcow2 container,
81
+not the start of the qcow2 file.
82
+
83
+Logically the layout looks like
84
+
85
+ +-----------------------------+
86
+ | QCow2 header |
87
+ | QCow2 header extension X |
88
+ | QCow2 header extension FDE |
89
+ | QCow2 header extension ... |
90
+ | QCow2 header extension Z |
91
+ +-----------------------------+
92
+ | ....other QCow2 tables.... |
93
+ . .
94
+ . .
95
+ +-----------------------------+
96
+ | +-------------------------+ |
97
+ | | LUKS partition header | |
98
+ | +-------------------------+ |
99
+ | | LUKS key material 1 | |
100
+ | +-------------------------+ |
101
+ | | LUKS key material 2 | |
102
+ | +-------------------------+ |
103
+ | | LUKS key material ... | |
104
+ | +-------------------------+ |
105
+ | | LUKS key material 8 | |
106
+ | +-------------------------+ |
107
+ +-----------------------------+
108
+ | QCow2 cluster payload |
109
+ . .
110
+ . .
111
+ . .
112
+ | |
113
+ +-----------------------------+
114
+
115
+== Data encryption ==
116
+
117
+When an encryption method is requested in the header, the image payload
118
+data must be encrypted/decrypted on every write/read. The image headers
119
+and metadata are never encrypted.
120
+
121
+The algorithms used for encryption vary depending on the method
122
+
123
+ - AES:
124
+
125
+ The AES cipher, in CBC mode, with 256 bit keys.
126
+
127
+ Initialization vectors generated using plain64 method, with
128
+ the virtual disk sector as the input tweak.
129
+
130
+ This format is no longer supported in QEMU system emulators, due
131
+ to a number of design flaws affecting its security. It is only
132
+ supported in the command line tools for the sake of back compatibility
133
+ and data liberation.
134
+
135
+ - LUKS:
136
+
137
+ The algorithms are specified in the LUKS header.
138
+
139
+ Initialization vectors generated using the method specified
140
+ in the LUKS header, with the physical disk sector as the
141
+ input tweak.
142
143
== Host cluster management ==
144
145
--
146
1.8.3.1
147
148
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
This extends the 087 iotest to cover LUKS encryption when doing
4
blockdev-add.
5
6
Two further tests are added to validate read/write of LUKS
7
encrypted images with a single file and with a backing file.
8
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
12
Message-id: 20170623162419.26068-15-berrange@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/087 | 35 ++++++++++++++++++-
16
tests/qemu-iotests/087.out | 14 +++++++-
17
tests/qemu-iotests/188 | 76 ++++++++++++++++++++++++++++++++++++++++
18
tests/qemu-iotests/188.out | 18 ++++++++++
19
tests/qemu-iotests/189 | 86 ++++++++++++++++++++++++++++++++++++++++++++++
20
tests/qemu-iotests/189.out | 26 ++++++++++++++
21
tests/qemu-iotests/group | 2 ++
22
7 files changed, 255 insertions(+), 2 deletions(-)
23
create mode 100755 tests/qemu-iotests/188
24
create mode 100644 tests/qemu-iotests/188.out
25
create mode 100755 tests/qemu-iotests/189
26
create mode 100644 tests/qemu-iotests/189.out
27
28
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/087
31
+++ b/tests/qemu-iotests/087
32
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
33
EOF
34
35
echo
36
-echo === Encrypted image ===
37
+echo === Encrypted image QCow ===
38
echo
39
40
_make_test_img --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 $size
41
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
42
EOF
43
44
echo
45
+echo === Encrypted image LUKS ===
46
+echo
47
+
48
+_make_test_img --object secret,id=sec0,data=123456 -o encrypt.format=luks,encrypt.key-secret=sec0 $size
49
+run_qemu <<EOF
50
+{ "execute": "qmp_capabilities" }
51
+{ "execute": "object-add",
52
+ "arguments": {
53
+ "qom-type": "secret",
54
+ "id": "sec0",
55
+ "props": {
56
+ "data": "123456"
57
+ }
58
+ }
59
+}
60
+{ "execute": "blockdev-add",
61
+ "arguments": {
62
+ "driver": "$IMGFMT",
63
+ "node-name": "disk",
64
+ "file": {
65
+ "driver": "file",
66
+ "filename": "$TEST_IMG"
67
+ },
68
+ "encrypt": {
69
+ "format": "luks",
70
+ "key-secret": "sec0"
71
+ }
72
+ }
73
+ }
74
+{ "execute": "quit" }
75
+EOF
76
+
77
+echo
78
echo === Missing driver ===
79
echo
80
81
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
82
index XXXXXXX..XXXXXXX 100644
83
--- a/tests/qemu-iotests/087.out
84
+++ b/tests/qemu-iotests/087.out
85
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
86
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
87
88
89
-=== Encrypted image ===
90
+=== Encrypted image QCow ===
91
92
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
93
Testing:
94
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
95
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
96
97
98
+=== Encrypted image LUKS ===
99
+
100
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encrypt.format=luks encrypt.key-secret=sec0
101
+Testing:
102
+QMP_VERSION
103
+{"return": {}}
104
+{"return": {}}
105
+{"return": {}}
106
+{"return": {}}
107
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
108
+
109
+
110
=== Missing driver ===
111
112
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on encrypt.key-secret=sec0
113
diff --git a/tests/qemu-iotests/188 b/tests/qemu-iotests/188
114
new file mode 100755
115
index XXXXXXX..XXXXXXX
116
--- /dev/null
117
+++ b/tests/qemu-iotests/188
118
@@ -XXX,XX +XXX,XX @@
119
+#!/bin/bash
120
+#
121
+# Test encrypted read/write using plain bdrv_read/bdrv_write
122
+#
123
+# Copyright (C) 2017 Red Hat, Inc.
124
+#
125
+# This program is free software; you can redistribute it and/or modify
126
+# it under the terms of the GNU General Public License as published by
127
+# the Free Software Foundation; either version 2 of the License, or
128
+# (at your option) any later version.
129
+#
130
+# This program is distributed in the hope that it will be useful,
131
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
132
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133
+# GNU General Public License for more details.
134
+#
135
+# You should have received a copy of the GNU General Public License
136
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
137
+#
138
+
139
+# creator
140
+owner=berrange@redhat.com
141
+
142
+seq=`basename $0`
143
+echo "QA output created by $seq"
144
+
145
+here=`pwd`
146
+status=1    # failure is the default!
147
+
148
+_cleanup()
149
+{
150
+    _cleanup_test_img
151
+}
152
+trap "_cleanup; exit \$status" 0 1 2 3 15
153
+
154
+# get standard environment, filters and checks
155
+. ./common.rc
156
+. ./common.filter
157
+
158
+_supported_fmt qcow2
159
+_supported_proto generic
160
+_supported_os Linux
161
+
162
+
163
+size=16M
164
+
165
+SECRET="secret,id=sec0,data=astrochicken"
166
+SECRETALT="secret,id=sec0,data=platypus"
167
+
168
+_make_test_img --object $SECRET -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
169
+
170
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,encrypt.key-secret=sec0"
171
+
172
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
173
+
174
+echo
175
+echo "== reading whole image =="
176
+$QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
177
+
178
+echo
179
+echo "== rewriting whole image =="
180
+$QEMU_IO --object $SECRET -c "write -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
181
+
182
+echo
183
+echo "== verify pattern =="
184
+$QEMU_IO --object $SECRET -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
185
+
186
+echo
187
+echo "== verify open failure with wrong password =="
188
+$QEMU_IO --object $SECRETALT -c "read -P 0xa 0 $size" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
189
+
190
+
191
+# success, all done
192
+echo "*** done"
193
+rm -f $seq.full
194
+status=0
195
diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out
196
new file mode 100644
197
index XXXXXXX..XXXXXXX
198
--- /dev/null
199
+++ b/tests/qemu-iotests/188.out
200
@@ -XXX,XX +XXX,XX @@
201
+QA output created by 188
202
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
203
+
204
+== reading whole image ==
205
+read 16777216/16777216 bytes at offset 0
206
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
207
+
208
+== rewriting whole image ==
209
+wrote 16777216/16777216 bytes at offset 0
210
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
211
+
212
+== verify pattern ==
213
+read 16777216/16777216 bytes at offset 0
214
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
215
+
216
+== verify open failure with wrong password ==
217
+can't open: Invalid password, cannot unlock any keyslot
218
+*** done
219
diff --git a/tests/qemu-iotests/189 b/tests/qemu-iotests/189
220
new file mode 100755
221
index XXXXXXX..XXXXXXX
222
--- /dev/null
223
+++ b/tests/qemu-iotests/189
224
@@ -XXX,XX +XXX,XX @@
225
+#!/bin/bash
226
+#
227
+# Test encrypted read/write using backing files
228
+#
229
+# Copyright (C) 2017 Red Hat, Inc.
230
+#
231
+# This program is free software; you can redistribute it and/or modify
232
+# it under the terms of the GNU General Public License as published by
233
+# the Free Software Foundation; either version 2 of the License, or
234
+# (at your option) any later version.
235
+#
236
+# This program is distributed in the hope that it will be useful,
237
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
238
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
239
+# GNU General Public License for more details.
240
+#
241
+# You should have received a copy of the GNU General Public License
242
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
243
+#
244
+
245
+# creator
246
+owner=berrange@redhat.com
247
+
248
+seq=`basename $0`
249
+echo "QA output created by $seq"
250
+
251
+here=`pwd`
252
+status=1    # failure is the default!
253
+
254
+_cleanup()
255
+{
256
+    _cleanup_test_img
257
+}
258
+trap "_cleanup; exit \$status" 0 1 2 3 15
259
+
260
+# get standard environment, filters and checks
261
+. ./common.rc
262
+. ./common.filter
263
+
264
+_supported_fmt qcow2
265
+_supported_proto generic
266
+_supported_os Linux
267
+
268
+
269
+size=16M
270
+TEST_IMG_BASE=$TEST_IMG.base
271
+SECRET0="secret,id=sec0,data=astrochicken"
272
+SECRET1="secret,id=sec1,data=furby"
273
+
274
+TEST_IMG_SAVE=$TEST_IMG
275
+TEST_IMG=$TEST_IMG_BASE
276
+echo "== create base =="
277
+_make_test_img --object $SECRET0 -o "encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10" $size
278
+TEST_IMG=$TEST_IMG_SAVE
279
+
280
+IMGSPECBASE="driver=$IMGFMT,file.filename=$TEST_IMG_BASE,encrypt.key-secret=sec0"
281
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,backing.driver=$IMGFMT,backing.file.filename=$TEST_IMG_BASE,backing.encrypt.key-secret=sec0,encrypt.key-secret=sec1"
282
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
283
+
284
+echo
285
+echo "== writing whole image =="
286
+$QEMU_IO --object $SECRET0 -c "write -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
287
+
288
+echo
289
+echo "== verify pattern =="
290
+$QEMU_IO --object $SECRET0 -c "read -P 0xa 0 $size" --image-opts $IMGSPECBASE | _filter_qemu_io | _filter_testdir
291
+
292
+echo "== create overlay =="
293
+_make_test_img --object $SECRET1 -o "encrypt.format=luks,encrypt.key-secret=sec1,encrypt.iter-time=10" -b "$TEST_IMG_BASE" $size
294
+
295
+echo
296
+echo "== writing part of a cluster =="
297
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "write -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
298
+
299
+echo
300
+echo "== verify pattern =="
301
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0xe 0 1024" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
302
+echo
303
+echo "== verify pattern =="
304
+$QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0xa 1024 64512" --image-opts $IMGSPEC | _filter_qemu_io | _filter_testdir
305
+
306
+
307
+# success, all done
308
+echo "*** done"
309
+rm -f $seq.full
310
+status=0
311
diff --git a/tests/qemu-iotests/189.out b/tests/qemu-iotests/189.out
312
new file mode 100644
313
index XXXXXXX..XXXXXXX
314
--- /dev/null
315
+++ b/tests/qemu-iotests/189.out
316
@@ -XXX,XX +XXX,XX @@
317
+QA output created by 189
318
+== create base ==
319
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
320
+
321
+== writing whole image ==
322
+wrote 16777216/16777216 bytes at offset 0
323
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
324
+
325
+== verify pattern ==
326
+read 16777216/16777216 bytes at offset 0
327
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
328
+== create overlay ==
329
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 backing_file=TEST_DIR/t.IMGFMT.base encrypt.format=luks encrypt.key-secret=sec1 encrypt.iter-time=10
330
+
331
+== writing part of a cluster ==
332
+wrote 1024/1024 bytes at offset 0
333
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
334
+
335
+== verify pattern ==
336
+read 1024/1024 bytes at offset 0
337
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
338
+
339
+== verify pattern ==
340
+read 64512/64512 bytes at offset 1024
341
+63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
342
+*** done
343
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
344
index XXXXXXX..XXXXXXX 100644
345
--- a/tests/qemu-iotests/group
346
+++ b/tests/qemu-iotests/group
347
@@ -XXX,XX +XXX,XX @@
348
182 rw auto quick
349
183 rw auto migration
350
185 rw auto
351
+188 rw auto quick
352
+189 rw auto quick
353
--
354
1.8.3.1
355
356
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
The 138 and 158 iotests exercise the legacy qcow2 aes encryption
4
code path and they work fine with qcow v1 too.
5
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
Message-id: 20170623162419.26068-16-berrange@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/134 | 2 +-
13
tests/qemu-iotests/158 | 2 +-
14
2 files changed, 2 insertions(+), 2 deletions(-)
15
16
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/134
19
+++ b/tests/qemu-iotests/134
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
21
. ./common.rc
22
. ./common.filter
23
24
-_supported_fmt qcow2
25
+_supported_fmt qcow qcow2
26
_supported_proto generic
27
_unsupported_proto vxhs
28
_supported_os Linux
29
diff --git a/tests/qemu-iotests/158 b/tests/qemu-iotests/158
30
index XXXXXXX..XXXXXXX 100755
31
--- a/tests/qemu-iotests/158
32
+++ b/tests/qemu-iotests/158
33
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
34
. ./common.rc
35
. ./common.filter
36
37
-_supported_fmt qcow2
38
+_supported_fmt qcow qcow2
39
_supported_proto generic
40
_unsupported_proto vxhs
41
_supported_os Linux
42
--
43
1.8.3.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
While the crypto layer uses a fixed option name "key-secret",
4
the upper block layer may have a prefix on the options. e.g.
5
"encrypt.key-secret", in order to avoid clashes between crypto
6
option names & other block option names. To ensure the crypto
7
layer can report accurate error messages, we must tell it what
8
option name prefix was used.
9
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
13
Message-id: 20170623162419.26068-19-berrange@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/crypto.c | 4 ++--
17
block/qcow.c | 7 ++++---
18
block/qcow2.c | 8 ++++----
19
crypto/block-luks.c | 8 ++++++--
20
crypto/block-qcow.c | 8 ++++++--
21
crypto/block.c | 6 ++++--
22
crypto/blockpriv.h | 2 ++
23
include/crypto/block.h | 6 +++++-
24
tests/test-crypto-block.c | 8 ++++----
25
9 files changed, 37 insertions(+), 20 deletions(-)
26
27
diff --git a/block/crypto.c b/block/crypto.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/crypto.c
30
+++ b/block/crypto.c
31
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
32
if (flags & BDRV_O_NO_IO) {
33
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
34
}
35
- crypto->block = qcrypto_block_open(open_opts,
36
+ crypto->block = qcrypto_block_open(open_opts, NULL,
37
block_crypto_read_func,
38
bs,
39
cflags,
40
@@ -XXX,XX +XXX,XX @@ static int block_crypto_create_generic(QCryptoBlockFormat format,
41
return -1;
42
}
43
44
- crypto = qcrypto_block_create(create_opts,
45
+ crypto = qcrypto_block_create(create_opts, NULL,
46
block_crypto_init_func,
47
block_crypto_write_func,
48
&data,
49
diff --git a/block/qcow.c b/block/qcow.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/qcow.c
52
+++ b/block/qcow.c
53
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
54
if (flags & BDRV_O_NO_IO) {
55
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
56
}
57
- s->crypto = qcrypto_block_open(crypto_opts, NULL, NULL,
58
- cflags, errp);
59
+ s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
60
+ NULL, NULL, cflags, errp);
61
if (!s->crypto) {
62
ret = -EINVAL;
63
goto fail;
64
@@ -XXX,XX +XXX,XX @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
65
goto exit;
66
}
67
68
- crypto = qcrypto_block_create(crypto_opts, NULL, NULL, NULL, errp);
69
+ crypto = qcrypto_block_create(crypto_opts, "encrypt.",
70
+ NULL, NULL, NULL, errp);
71
if (!crypto) {
72
ret = -EINVAL;
73
goto exit;
74
diff --git a/block/qcow2.c b/block/qcow2.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/qcow2.c
77
+++ b/block/qcow2.c
78
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
79
if (flags & BDRV_O_NO_IO) {
80
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
81
}
82
- s->crypto = qcrypto_block_open(s->crypto_opts,
83
+ s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
84
qcow2_crypto_hdr_read_func,
85
bs, cflags, errp);
86
if (!s->crypto) {
87
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
88
if (flags & BDRV_O_NO_IO) {
89
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
90
}
91
- s->crypto = qcrypto_block_open(s->crypto_opts, NULL, NULL,
92
- cflags, errp);
93
+ s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
94
+ NULL, NULL, cflags, errp);
95
if (!s->crypto) {
96
ret = -EINVAL;
97
goto fail;
98
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
99
}
100
s->crypt_method_header = fmt;
101
102
- crypto = qcrypto_block_create(cryptoopts,
103
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
104
qcow2_crypto_hdr_init_func,
105
qcow2_crypto_hdr_write_func,
106
bs, errp);
107
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/crypto/block-luks.c
110
+++ b/crypto/block-luks.c
111
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_find_key(QCryptoBlock *block,
112
static int
113
qcrypto_block_luks_open(QCryptoBlock *block,
114
QCryptoBlockOpenOptions *options,
115
+ const char *optprefix,
116
QCryptoBlockReadFunc readfunc,
117
void *opaque,
118
unsigned int flags,
119
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_open(QCryptoBlock *block,
120
121
if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
122
if (!options->u.luks.key_secret) {
123
- error_setg(errp, "Parameter 'key-secret' is required for cipher");
124
+ error_setg(errp, "Parameter '%skey-secret' is required for cipher",
125
+ optprefix ? optprefix : "");
126
return -1;
127
}
128
password = qcrypto_secret_lookup_as_utf8(
129
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
130
static int
131
qcrypto_block_luks_create(QCryptoBlock *block,
132
QCryptoBlockCreateOptions *options,
133
+ const char *optprefix,
134
QCryptoBlockInitFunc initfunc,
135
QCryptoBlockWriteFunc writefunc,
136
void *opaque,
137
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_create(QCryptoBlock *block,
138
* be silently ignored, for compatibility with dm-crypt */
139
140
if (!options->u.luks.key_secret) {
141
- error_setg(errp, "Parameter 'key-secret' is required for cipher");
142
+ error_setg(errp, "Parameter '%skey-secret' is required for cipher",
143
+ optprefix ? optprefix : "");
144
return -1;
145
}
146
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
147
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/crypto/block-qcow.c
150
+++ b/crypto/block-qcow.c
151
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_init(QCryptoBlock *block,
152
static int
153
qcrypto_block_qcow_open(QCryptoBlock *block,
154
QCryptoBlockOpenOptions *options,
155
+ const char *optprefix,
156
QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
157
void *opaque G_GNUC_UNUSED,
158
unsigned int flags,
159
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
160
} else {
161
if (!options->u.qcow.key_secret) {
162
error_setg(errp,
163
- "Parameter 'key-secret' is required for cipher");
164
+ "Parameter '%skey-secret' is required for cipher",
165
+ optprefix ? optprefix : "");
166
return -1;
167
}
168
return qcrypto_block_qcow_init(block,
169
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
170
static int
171
qcrypto_block_qcow_create(QCryptoBlock *block,
172
QCryptoBlockCreateOptions *options,
173
+ const char *optprefix,
174
QCryptoBlockInitFunc initfunc G_GNUC_UNUSED,
175
QCryptoBlockWriteFunc writefunc G_GNUC_UNUSED,
176
void *opaque G_GNUC_UNUSED,
177
Error **errp)
178
{
179
if (!options->u.qcow.key_secret) {
180
- error_setg(errp, "Parameter 'key-secret' is required for cipher");
181
+ error_setg(errp, "Parameter '%skey-secret' is required for cipher",
182
+ optprefix ? optprefix : "");
183
return -1;
184
}
185
/* QCow2 has no special header, since everything is hardwired */
186
diff --git a/crypto/block.c b/crypto/block.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/crypto/block.c
189
+++ b/crypto/block.c
190
@@ -XXX,XX +XXX,XX @@ bool qcrypto_block_has_format(QCryptoBlockFormat format,
191
192
193
QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
194
+ const char *optprefix,
195
QCryptoBlockReadFunc readfunc,
196
void *opaque,
197
unsigned int flags,
198
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
199
200
block->driver = qcrypto_block_drivers[options->format];
201
202
- if (block->driver->open(block, options,
203
+ if (block->driver->open(block, options, optprefix,
204
readfunc, opaque, flags, errp) < 0) {
205
g_free(block);
206
return NULL;
207
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
208
209
210
QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
211
+ const char *optprefix,
212
QCryptoBlockInitFunc initfunc,
213
QCryptoBlockWriteFunc writefunc,
214
void *opaque,
215
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
216
217
block->driver = qcrypto_block_drivers[options->format];
218
219
- if (block->driver->create(block, options, initfunc,
220
+ if (block->driver->create(block, options, optprefix, initfunc,
221
writefunc, opaque, errp) < 0) {
222
g_free(block);
223
return NULL;
224
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
225
index XXXXXXX..XXXXXXX 100644
226
--- a/crypto/blockpriv.h
227
+++ b/crypto/blockpriv.h
228
@@ -XXX,XX +XXX,XX @@ struct QCryptoBlock {
229
struct QCryptoBlockDriver {
230
int (*open)(QCryptoBlock *block,
231
QCryptoBlockOpenOptions *options,
232
+ const char *optprefix,
233
QCryptoBlockReadFunc readfunc,
234
void *opaque,
235
unsigned int flags,
236
@@ -XXX,XX +XXX,XX @@ struct QCryptoBlockDriver {
237
238
int (*create)(QCryptoBlock *block,
239
QCryptoBlockCreateOptions *options,
240
+ const char *optprefix,
241
QCryptoBlockInitFunc initfunc,
242
QCryptoBlockWriteFunc writefunc,
243
void *opaque,
244
diff --git a/include/crypto/block.h b/include/crypto/block.h
245
index XXXXXXX..XXXXXXX 100644
246
--- a/include/crypto/block.h
247
+++ b/include/crypto/block.h
248
@@ -XXX,XX +XXX,XX @@ typedef enum {
249
/**
250
* qcrypto_block_open:
251
* @options: the encryption options
252
+ * @optprefix: name prefix for options
253
* @readfunc: callback for reading data from the volume
254
* @opaque: data to pass to @readfunc
255
* @flags: bitmask of QCryptoBlockOpenFlags values
256
@@ -XXX,XX +XXX,XX @@ typedef enum {
257
* Returns: a block encryption format, or NULL on error
258
*/
259
QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
260
+ const char *optprefix,
261
QCryptoBlockReadFunc readfunc,
262
void *opaque,
263
unsigned int flags,
264
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
265
266
/**
267
* qcrypto_block_create:
268
- * @format: the encryption format
269
+ * @options: the encryption options
270
+ * @optprefix: name prefix for options
271
* @initfunc: callback for initializing volume header
272
* @writefunc: callback for writing data to the volume header
273
* @opaque: data to pass to @initfunc and @writefunc
274
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
275
* Returns: a block encryption format, or NULL on error
276
*/
277
QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
278
+ const char *optprefix,
279
QCryptoBlockInitFunc initfunc,
280
QCryptoBlockWriteFunc writefunc,
281
void *opaque,
282
diff --git a/tests/test-crypto-block.c b/tests/test-crypto-block.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/tests/test-crypto-block.c
285
+++ b/tests/test-crypto-block.c
286
@@ -XXX,XX +XXX,XX @@ static void test_block(gconstpointer opaque)
287
memset(&header, 0, sizeof(header));
288
buffer_init(&header, "header");
289
290
- blk = qcrypto_block_create(data->create_opts,
291
+ blk = qcrypto_block_create(data->create_opts, NULL,
292
test_block_init_func,
293
test_block_write_func,
294
&header,
295
@@ -XXX,XX +XXX,XX @@ static void test_block(gconstpointer opaque)
296
object_unparent(sec);
297
298
/* Ensure we can't open without the secret */
299
- blk = qcrypto_block_open(data->open_opts,
300
+ blk = qcrypto_block_open(data->open_opts, NULL,
301
test_block_read_func,
302
&header,
303
0,
304
@@ -XXX,XX +XXX,XX @@ static void test_block(gconstpointer opaque)
305
g_assert(blk == NULL);
306
307
/* Ensure we can't open without the secret, unless NO_IO */
308
- blk = qcrypto_block_open(data->open_opts,
309
+ blk = qcrypto_block_open(data->open_opts, NULL,
310
test_block_read_func,
311
&header,
312
QCRYPTO_BLOCK_OPEN_NO_IO,
313
@@ -XXX,XX +XXX,XX @@ static void test_block(gconstpointer opaque)
314
315
/* Now open for real with secret */
316
sec = test_block_secret();
317
- blk = qcrypto_block_open(data->open_opts,
318
+ blk = qcrypto_block_open(data->open_opts, NULL,
319
test_block_read_func,
320
&header,
321
0,
322
--
323
1.8.3.1
324
325
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Currently 'qemu-img info' reports a simple "encrypted: yes"
4
field. This is not very useful now that qcow2 can support
5
multiple encryption formats. Users want to know which format
6
is in use and some data related to it.
7
8
Wire up usage of the qcrypto_block_get_info() method so that
9
'qemu-img info' can report about the encryption format
10
and parameters in use
11
12
$ qemu-img create \
13
--object secret,id=sec0,data=123456 \
14
-o encrypt.format=luks,encrypt.key-secret=sec0 \
15
-f qcow2 demo.qcow2 1G
16
Formatting 'demo.qcow2', fmt=qcow2 size=1073741824 \
17
encryption=off encrypt.format=luks encrypt.key-secret=sec0 \
18
cluster_size=65536 lazy_refcounts=off refcount_bits=16
19
20
$ qemu-img info demo.qcow2
21
image: demo.qcow2
22
file format: qcow2
23
virtual size: 1.0G (1073741824 bytes)
24
disk size: 480K
25
encrypted: yes
26
cluster_size: 65536
27
Format specific information:
28
compat: 1.1
29
lazy refcounts: false
30
refcount bits: 16
31
encrypt:
32
ivgen alg: plain64
33
hash alg: sha256
34
cipher alg: aes-256
35
uuid: 3fa930c4-58c8-4ef7-b3c5-314bb5af21f3
36
format: luks
37
cipher mode: xts
38
slots:
39
[0]:
40
active: true
41
iters: 1839058
42
key offset: 4096
43
stripes: 4000
44
[1]:
45
active: false
46
key offset: 262144
47
[2]:
48
active: false
49
key offset: 520192
50
[3]:
51
active: false
52
key offset: 778240
53
[4]:
54
active: false
55
key offset: 1036288
56
[5]:
57
active: false
58
key offset: 1294336
59
[6]:
60
active: false
61
key offset: 1552384
62
[7]:
63
active: false
64
key offset: 1810432
65
payload offset: 2068480
66
master key iters: 438487
67
corrupt: false
68
69
With the legacy "AES" encryption we just report the format
70
name
71
72
$ qemu-img create \
73
--object secret,id=sec0,data=123456 \
74
-o encrypt.format=aes,encrypt.key-secret=sec0 \
75
-f qcow2 demo.qcow2 1G
76
Formatting 'demo.qcow2', fmt=qcow2 size=1073741824 \
77
encryption=off encrypt.format=aes encrypt.key-secret=sec0 \
78
cluster_size=65536 lazy_refcounts=off refcount_bits=16
79
80
$ ./qemu-img info demo.qcow2
81
image: demo.qcow2
82
file format: qcow2
83
virtual size: 1.0G (1073741824 bytes)
84
disk size: 196K
85
encrypted: yes
86
cluster_size: 65536
87
Format specific information:
88
compat: 1.1
89
lazy refcounts: false
90
refcount bits: 16
91
encrypt:
92
format: aes
93
corrupt: false
94
95
Reviewed-by: Alberto Garcia <berto@igalia.com>
96
Reviewed-by: Max Reitz <mreitz@redhat.com>
97
Reviewed-by: Eric Blake <eblake@redhat.com>
98
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
99
Message-id: 20170623162419.26068-20-berrange@redhat.com
100
Signed-off-by: Max Reitz <mreitz@redhat.com>
101
---
102
block/qcow2.c | 32 +++++++++++++++++++++++++++++++-
103
qapi/block-core.json | 27 ++++++++++++++++++++++++++-
104
2 files changed, 57 insertions(+), 2 deletions(-)
105
106
diff --git a/block/qcow2.c b/block/qcow2.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/qcow2.c
109
+++ b/block/qcow2.c
110
@@ -XXX,XX +XXX,XX @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
111
static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
112
{
113
BDRVQcow2State *s = bs->opaque;
114
- ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
115
+ ImageInfoSpecific *spec_info;
116
+ QCryptoBlockInfo *encrypt_info = NULL;
117
118
+ if (s->crypto != NULL) {
119
+ encrypt_info = qcrypto_block_get_info(s->crypto, &error_abort);
120
+ }
121
+
122
+ spec_info = g_new(ImageInfoSpecific, 1);
123
*spec_info = (ImageInfoSpecific){
124
.type = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
125
.u.qcow2.data = g_new(ImageInfoSpecificQCow2, 1),
126
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
127
assert(false);
128
}
129
130
+ if (encrypt_info) {
131
+ ImageInfoSpecificQCow2Encryption *qencrypt =
132
+ g_new(ImageInfoSpecificQCow2Encryption, 1);
133
+ switch (encrypt_info->format) {
134
+ case Q_CRYPTO_BLOCK_FORMAT_QCOW:
135
+ qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_AES;
136
+ qencrypt->u.aes = encrypt_info->u.qcow;
137
+ break;
138
+ case Q_CRYPTO_BLOCK_FORMAT_LUKS:
139
+ qencrypt->format = BLOCKDEV_QCOW2_ENCRYPTION_FORMAT_LUKS;
140
+ qencrypt->u.luks = encrypt_info->u.luks;
141
+ break;
142
+ default:
143
+ abort();
144
+ }
145
+ /* Since we did shallow copy above, erase any pointers
146
+ * in the original info */
147
+ memset(&encrypt_info->u, 0, sizeof(encrypt_info->u));
148
+ qapi_free_QCryptoBlockInfo(encrypt_info);
149
+
150
+ spec_info->u.qcow2.data->has_encrypt = true;
151
+ spec_info->u.qcow2.data->encrypt = qencrypt;
152
+ }
153
+
154
return spec_info;
155
}
156
157
diff --git a/qapi/block-core.json b/qapi/block-core.json
158
index XXXXXXX..XXXXXXX 100644
159
--- a/qapi/block-core.json
160
+++ b/qapi/block-core.json
161
@@ -XXX,XX +XXX,XX @@
162
'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
163
164
##
165
+# @ImageInfoSpecificQCow2EncryptionBase:
166
+#
167
+# @format: The encryption format
168
+#
169
+# Since: 2.10
170
+##
171
+{ 'struct': 'ImageInfoSpecificQCow2EncryptionBase',
172
+ 'data': { 'format': 'BlockdevQcow2EncryptionFormat'}}
173
+
174
+##
175
+# @ImageInfoSpecificQCow2Encryption:
176
+#
177
+# Since: 2.10
178
+##
179
+{ 'union': 'ImageInfoSpecificQCow2Encryption',
180
+ 'base': 'ImageInfoSpecificQCow2EncryptionBase',
181
+ 'discriminator': 'format',
182
+ 'data': { 'aes': 'QCryptoBlockInfoQCow',
183
+ 'luks': 'QCryptoBlockInfoLUKS' } }
184
+
185
+##
186
# @ImageInfoSpecificQCow2:
187
#
188
# @compat: compatibility level
189
@@ -XXX,XX +XXX,XX @@
190
#
191
# @refcount-bits: width of a refcount entry in bits (since 2.3)
192
#
193
+# @encrypt: details about encryption parameters; only set if image
194
+# is encrypted (since 2.10)
195
+#
196
# Since: 1.7
197
##
198
{ 'struct': 'ImageInfoSpecificQCow2',
199
@@ -XXX,XX +XXX,XX @@
200
'compat': 'str',
201
'*lazy-refcounts': 'bool',
202
'*corrupt': 'bool',
203
- 'refcount-bits': 'int'
204
+ 'refcount-bits': 'int',
205
+ '*encrypt': 'ImageInfoSpecificQCow2Encryption'
206
} }
207
208
##
209
--
210
1.8.3.1
211
212
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Expand the image format docs to cover the new options for
4
the qcow, qcow2 and luks disk image formats
5
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
Message-id: 20170623162419.26068-21-berrange@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
qemu-doc.texi | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
13
1 file changed, 115 insertions(+), 8 deletions(-)
14
15
diff --git a/qemu-doc.texi b/qemu-doc.texi
16
index XXXXXXX..XXXXXXX 100644
17
--- a/qemu-doc.texi
18
+++ b/qemu-doc.texi
19
@@ -XXX,XX +XXX,XX @@ File name of a base image (see @option{create} subcommand)
20
@item backing_fmt
21
Image format of the base image
22
@item encryption
23
-If this option is set to @code{on}, the image is encrypted with 128-bit AES-CBC.
24
+This option is deprecated and equivalent to @code{encrypt.format=aes}
25
26
-The use of encryption in qcow and qcow2 images is considered to be flawed by
27
-modern cryptography standards, suffering from a number of design problems:
28
+@item encrypt.format
29
+
30
+If this is set to @code{luks}, it requests that the qcow2 payload (not
31
+qcow2 header) be encrypted using the LUKS format. The passphrase to
32
+use to unlock the LUKS key slot is given by the @code{encrypt.key-secret}
33
+parameter. LUKS encryption parameters can be tuned with the other
34
+@code{encrypt.*} parameters.
35
+
36
+If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
37
+The encryption key is given by the @code{encrypt.key-secret} parameter.
38
+This encryption format is considered to be flawed by modern cryptography
39
+standards, suffering from a number of design problems:
40
41
@itemize @minus
42
@item The AES-CBC cipher is used with predictable initialization vectors based
43
@@ -XXX,XX +XXX,XX @@ original file must then be securely erased using a program like shred,
44
though even this is ineffective with many modern storage technologies.
45
@end itemize
46
47
-Use of qcow / qcow2 encryption with QEMU is deprecated, and support for
48
-it will go away in a future release. Users are recommended to use an
49
-alternative encryption technology such as the Linux dm-crypt / LUKS
50
-system.
51
+The use of this is no longer supported in system emulators. Support only
52
+remains in the command line utilities, for the purposes of data liberation
53
+and interoperability with old versions of QEMU. The @code{luks} format
54
+should be used instead.
55
+
56
+@item encrypt.key-secret
57
+
58
+Provides the ID of a @code{secret} object that contains the passphrase
59
+(@code{encrypt.format=luks}) or encryption key (@code{encrypt.format=aes}).
60
+
61
+@item encrypt.cipher-alg
62
+
63
+Name of the cipher algorithm and key length. Currently defaults
64
+to @code{aes-256}. Only used when @code{encrypt.format=luks}.
65
+
66
+@item encrypt.cipher-mode
67
+
68
+Name of the encryption mode to use. Currently defaults to @code{xts}.
69
+Only used when @code{encrypt.format=luks}.
70
+
71
+@item encrypt.ivgen-alg
72
+
73
+Name of the initialization vector generator algorithm. Currently defaults
74
+to @code{plain64}. Only used when @code{encrypt.format=luks}.
75
+
76
+@item encrypt.ivgen-hash-alg
77
+
78
+Name of the hash algorithm to use with the initialization vector generator
79
+(if required). Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
80
+
81
+@item encrypt.hash-alg
82
+
83
+Name of the hash algorithm to use for PBKDF algorithm
84
+Defaults to @code{sha256}. Only used when @code{encrypt.format=luks}.
85
+
86
+@item encrypt.iter-time
87
+
88
+Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
89
+Defaults to @code{2000}. Only used when @code{encrypt.format=luks}.
90
91
@item cluster_size
92
Changes the qcow2 cluster size (must be between 512 and 2M). Smaller cluster
93
@@ -XXX,XX +XXX,XX @@ Supported options:
94
@item backing_file
95
File name of a base image (see @option{create} subcommand)
96
@item encryption
97
-If this option is set to @code{on}, the image is encrypted.
98
+This option is deprecated and equivalent to @code{encrypt.format=aes}
99
+
100
+@item encrypt.format
101
+If this is set to @code{aes}, the image is encrypted with 128-bit AES-CBC.
102
+The encryption key is given by the @code{encrypt.key-secret} parameter.
103
+This encryption format is considered to be flawed by modern cryptography
104
+standards, suffering from a number of design problems enumerated previously
105
+against the @code{qcow2} image format.
106
+
107
+The use of this is no longer supported in system emulators. Support only
108
+remains in the command line utilities, for the purposes of data liberation
109
+and interoperability with old versions of QEMU.
110
+
111
+Users requiring native encryption should use the @code{qcow2} format
112
+instead with @code{encrypt.format=luks}.
113
+
114
+@item encrypt.key-secret
115
+
116
+Provides the ID of a @code{secret} object that contains the encryption
117
+key (@code{encrypt.format=aes}).
118
+
119
+@end table
120
+
121
+@item luks
122
+
123
+LUKS v1 encryption format, compatible with Linux dm-crypt/cryptsetup
124
+
125
+Supported options:
126
+@table @code
127
+
128
+@item key-secret
129
+
130
+Provides the ID of a @code{secret} object that contains the passphrase.
131
+
132
+@item cipher-alg
133
+
134
+Name of the cipher algorithm and key length. Currently defaults
135
+to @code{aes-256}.
136
+
137
+@item cipher-mode
138
+
139
+Name of the encryption mode to use. Currently defaults to @code{xts}.
140
+
141
+@item ivgen-alg
142
+
143
+Name of the initialization vector generator algorithm. Currently defaults
144
+to @code{plain64}.
145
+
146
+@item ivgen-hash-alg
147
+
148
+Name of the hash algorithm to use with the initialization vector generator
149
+(if required). Defaults to @code{sha256}.
150
+
151
+@item hash-alg
152
+
153
+Name of the hash algorithm to use for PBKDF algorithm
154
+Defaults to @code{sha256}.
155
+
156
+@item iter-time
157
+
158
+Amount of time, in milliseconds, to use for PBKDF algorithm per key slot.
159
+Defaults to @code{2000}.
160
+
161
@end table
162
163
@item vdi
164
--
165
1.8.3.1
166
167
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Test 181 only works for formats which support live migration (naturally,
4
as it is a live migration test). Disable it for all formats which do
5
not.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20170621131157.16584-1-mreitz@redhat.com
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/181 | 2 ++
13
1 file changed, 2 insertions(+)
14
15
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/181
18
+++ b/tests/qemu-iotests/181
19
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
20
. ./common.qemu
21
22
_supported_fmt generic
23
+# Formats that do not support live migration
24
+_unsupported_fmt qcow vdi vhdx vmdk vpc vvfat
25
_supported_proto generic
26
_supported_os Linux
27
28
--
29
1.8.3.1
30
31
diff view generated by jsdifflib
Deleted patch
1
From: "sochin.jiang" <sochin.jiang@huawei.com>
2
1
3
mirror_complete opens the backing chain, which should have the same
4
AioContext as the top when using iothreads. Make the code guarantee
5
this, which fixes a failed assertion in bdrv_attach_child.
6
7
Signed-off-by: sochin.jiang <sochin.jiang@huawei.com>
8
Message-id: 1498475064-39816-1-git-send-email-sochin.jiang@huawei.com
9
[mreitz: Reworded commit message]
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block.c | 1 +
13
1 file changed, 1 insertion(+)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
20
ret = -EINVAL;
21
goto free_exit;
22
}
23
+ bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
24
25
/* Hook up the backing file link; drop our reference, bs owns the
26
* backing_hd reference now */
27
--
28
1.8.3.1
29
30
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: John Snow <jsnow@redhat.com>
5
Message-id: 20170628120530.31251-2-vsementsov@virtuozzo.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
docs/interop/qcow2.txt | 3 +--
9
1 file changed, 1 insertion(+), 2 deletions(-)
10
11
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/interop/qcow2.txt
14
+++ b/docs/interop/qcow2.txt
15
@@ -XXX,XX +XXX,XX @@ Structure of a bitmap directory entry:
16
17: granularity_bits
17
Granularity bits. Valid values: 0 - 63.
18
19
- Note: Qemu currently doesn't support granularity_bits
20
- greater than 31.
21
+ Note: Qemu currently supports only values 9 - 31.
22
23
Granularity is calculated as
24
granularity = 1 << granularity_bits
25
--
26
1.8.3.1
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
A bitmap directory entry is sometimes called a 'bitmap header'. This
4
patch leaves only one name - 'bitmap directory entry'. The name 'bitmap
5
header' creates misunderstandings with 'qcow2 header' and 'qcow2 bitmap
6
header extension' (which is extension of qcow2 header)
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Message-id: 20170628120530.31251-3-vsementsov@virtuozzo.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
docs/interop/qcow2.txt | 5 ++---
15
1 file changed, 2 insertions(+), 3 deletions(-)
16
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
20
+++ b/docs/interop/qcow2.txt
21
@@ -XXX,XX +XXX,XX @@ The fields of the bitmaps extension are:
22
23
8 - 15: bitmap_directory_size
24
Size of the bitmap directory in bytes. It is the cumulative
25
- size of all (nb_bitmaps) bitmap headers.
26
+ size of all (nb_bitmaps) bitmap directory entries.
27
28
16 - 23: bitmap_directory_offset
29
Offset into the image file at which the bitmap directory
30
@@ -XXX,XX +XXX,XX @@ Each bitmap saved in the image is described in a bitmap directory entry. The
31
bitmap directory is a contiguous area in the image file, whose starting offset
32
and length are given by the header extension fields bitmap_directory_offset and
33
bitmap_directory_size. The entries of the bitmap directory have variable
34
-length, depending on the lengths of the bitmap name and extra data. These
35
-entries are also called bitmap headers.
36
+length, depending on the lengths of the bitmap name and extra data.
37
38
Structure of a bitmap directory entry:
39
40
--
41
1.8.3.1
42
43
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Test that hbitmap iter is resistant to bitmap resetting.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Denis V. Lunev <den@openvz.org>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: 20170628120530.31251-5-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/test-hbitmap.c | 19 +++++++++++++++++++
13
1 file changed, 19 insertions(+)
14
15
diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/test-hbitmap.c
18
+++ b/tests/test-hbitmap.c
19
@@ -XXX,XX +XXX,XX @@ static void hbitmap_test_add(const char *testpath,
20
hbitmap_test_teardown);
21
}
22
23
+static void test_hbitmap_iter_and_reset(TestHBitmapData *data,
24
+ const void *unused)
25
+{
26
+ HBitmapIter hbi;
27
+
28
+ hbitmap_test_init(data, L1 * 2, 0);
29
+ hbitmap_set(data->hb, 0, data->size);
30
+
31
+ hbitmap_iter_init(&hbi, data->hb, BITS_PER_LONG - 1);
32
+
33
+ hbitmap_iter_next(&hbi);
34
+
35
+ hbitmap_reset_all(data->hb);
36
+ hbitmap_iter_next(&hbi);
37
+}
38
+
39
int main(int argc, char **argv)
40
{
41
g_test_init(&argc, &argv, NULL);
42
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
43
test_hbitmap_serialize_part);
44
hbitmap_test_add("/hbitmap/serialize/zeroes",
45
test_hbitmap_serialize_zeroes);
46
+
47
+ hbitmap_test_add("/hbitmap/iter/iter_and_reset",
48
+ test_hbitmap_iter_and_reset);
49
g_test_run();
50
51
return 0;
52
--
53
1.8.3.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add bdrv_dirty_bitmap_deserialize_ones() function, which is needed for
4
qcow2 bitmap loading, to handle unallocated bitmap parts, marked as
5
all-ones.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Message-id: 20170628120530.31251-7-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/dirty-bitmap.c | 7 +++++++
14
include/block/dirty-bitmap.h | 3 +++
15
include/qemu/hbitmap.h | 15 +++++++++++++++
16
util/hbitmap.c | 17 +++++++++++++++++
17
4 files changed, 42 insertions(+)
18
19
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/dirty-bitmap.c
22
+++ b/block/dirty-bitmap.c
23
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
24
hbitmap_deserialize_zeroes(bitmap->bitmap, start, count, finish);
25
}
26
27
+void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
28
+ uint64_t start, uint64_t count,
29
+ bool finish)
30
+{
31
+ hbitmap_deserialize_ones(bitmap->bitmap, start, count, finish);
32
+}
33
+
34
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap)
35
{
36
hbitmap_deserialize_finish(bitmap->bitmap);
37
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/dirty-bitmap.h
40
+++ b/include/block/dirty-bitmap.h
41
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap,
42
void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap,
43
uint64_t start, uint64_t count,
44
bool finish);
45
+void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
46
+ uint64_t start, uint64_t count,
47
+ bool finish);
48
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
49
50
/* Functions that require manual locking. */
51
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/qemu/hbitmap.h
54
+++ b/include/qemu/hbitmap.h
55
@@ -XXX,XX +XXX,XX @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count,
56
bool finish);
57
58
/**
59
+ * hbitmap_deserialize_ones
60
+ * @hb: HBitmap to operate on.
61
+ * @start: First bit to restore.
62
+ * @count: Number of bits to restore.
63
+ * @finish: Whether to call hbitmap_deserialize_finish automatically.
64
+ *
65
+ * Fills the bitmap with ones.
66
+ *
67
+ * If @finish is false, caller must call hbitmap_serialize_finish before using
68
+ * the bitmap.
69
+ */
70
+void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count,
71
+ bool finish);
72
+
73
+/**
74
* hbitmap_deserialize_finish
75
* @hb: HBitmap to operate on.
76
*
77
diff --git a/util/hbitmap.c b/util/hbitmap.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/util/hbitmap.c
80
+++ b/util/hbitmap.c
81
@@ -XXX,XX +XXX,XX @@ void hbitmap_deserialize_zeroes(HBitmap *hb, uint64_t start, uint64_t count,
82
}
83
}
84
85
+void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count,
86
+ bool finish)
87
+{
88
+ uint64_t el_count;
89
+ unsigned long *first;
90
+
91
+ if (!count) {
92
+ return;
93
+ }
94
+ serialization_chunk(hb, start, count, &first, &el_count);
95
+
96
+ memset(first, 0xff, el_count * sizeof(unsigned long));
97
+ if (finish) {
98
+ hbitmap_deserialize_finish(hb);
99
+ }
100
+}
101
+
102
void hbitmap_deserialize_finish(HBitmap *bitmap)
103
{
104
int64_t i, size, prev_size;
105
--
106
1.8.3.1
107
108
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This is needed for the following patch, which will introduce refcounts
4
checking for qcow2 bitmaps.
5
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: 20170628120530.31251-8-vsementsov@virtuozzo.com
10
[mreitz: s/inc_refcounts/qcow2_inc_refcounts_imrt/ in one more (new)
11
place]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/qcow2-refcount.c | 59 ++++++++++++++++++++++++++------------------------
15
block/qcow2.h | 4 ++++
16
2 files changed, 35 insertions(+), 28 deletions(-)
17
18
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/qcow2-refcount.c
21
+++ b/block/qcow2-refcount.c
22
@@ -XXX,XX +XXX,XX @@ static int realloc_refcount_array(BDRVQcow2State *s, void **array,
23
*
24
* Modifies the number of errors in res.
25
*/
26
-static int inc_refcounts(BlockDriverState *bs,
27
- BdrvCheckResult *res,
28
- void **refcount_table,
29
- int64_t *refcount_table_size,
30
- int64_t offset, int64_t size)
31
+int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
32
+ void **refcount_table,
33
+ int64_t *refcount_table_size,
34
+ int64_t offset, int64_t size)
35
{
36
BDRVQcow2State *s = bs->opaque;
37
uint64_t start, last, cluster_offset, k, refcount;
38
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
39
nb_csectors = ((l2_entry >> s->csize_shift) &
40
s->csize_mask) + 1;
41
l2_entry &= s->cluster_offset_mask;
42
- ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
43
- l2_entry & ~511, nb_csectors * 512);
44
+ ret = qcow2_inc_refcounts_imrt(bs, res,
45
+ refcount_table, refcount_table_size,
46
+ l2_entry & ~511, nb_csectors * 512);
47
if (ret < 0) {
48
goto fail;
49
}
50
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
51
}
52
53
/* Mark cluster as used */
54
- ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
55
- offset, s->cluster_size);
56
+ ret = qcow2_inc_refcounts_imrt(bs, res,
57
+ refcount_table, refcount_table_size,
58
+ offset, s->cluster_size);
59
if (ret < 0) {
60
goto fail;
61
}
62
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
63
l1_size2 = l1_size * sizeof(uint64_t);
64
65
/* Mark L1 table as used */
66
- ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
67
- l1_table_offset, l1_size2);
68
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, refcount_table_size,
69
+ l1_table_offset, l1_size2);
70
if (ret < 0) {
71
goto fail;
72
}
73
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
74
if (l2_offset) {
75
/* Mark L2 table as used */
76
l2_offset &= L1E_OFFSET_MASK;
77
- ret = inc_refcounts(bs, res, refcount_table, refcount_table_size,
78
- l2_offset, s->cluster_size);
79
+ ret = qcow2_inc_refcounts_imrt(bs, res,
80
+ refcount_table, refcount_table_size,
81
+ l2_offset, s->cluster_size);
82
if (ret < 0) {
83
goto fail;
84
}
85
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
86
}
87
88
res->corruptions_fixed++;
89
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
90
- offset, s->cluster_size);
91
+ ret = qcow2_inc_refcounts_imrt(bs, res,
92
+ refcount_table, nb_clusters,
93
+ offset, s->cluster_size);
94
if (ret < 0) {
95
return ret;
96
}
97
/* No need to check whether the refcount is now greater than 1:
98
* This area was just allocated and zeroed, so it can only be
99
- * exactly 1 after inc_refcounts() */
100
+ * exactly 1 after qcow2_inc_refcounts_imrt() */
101
continue;
102
103
resize_fail:
104
@@ -XXX,XX +XXX,XX @@ resize_fail:
105
}
106
107
if (offset != 0) {
108
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
109
- offset, s->cluster_size);
110
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters,
111
+ offset, s->cluster_size);
112
if (ret < 0) {
113
return ret;
114
}
115
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
116
}
117
118
/* header */
119
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
120
- 0, s->cluster_size);
121
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters,
122
+ 0, s->cluster_size);
123
if (ret < 0) {
124
return ret;
125
}
126
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
127
return ret;
128
}
129
}
130
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
131
- s->snapshots_offset, s->snapshots_size);
132
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters,
133
+ s->snapshots_offset, s->snapshots_size);
134
if (ret < 0) {
135
return ret;
136
}
137
138
/* refcount data */
139
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
140
- s->refcount_table_offset,
141
- s->refcount_table_size * sizeof(uint64_t));
142
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters,
143
+ s->refcount_table_offset,
144
+ s->refcount_table_size * sizeof(uint64_t));
145
if (ret < 0) {
146
return ret;
147
}
148
149
/* encryption */
150
if (s->crypto_header.length) {
151
- ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
152
- s->crypto_header.offset,
153
- s->crypto_header.length);
154
+ ret = qcow2_inc_refcounts_imrt(bs, res, refcount_table, nb_clusters,
155
+ s->crypto_header.offset,
156
+ s->crypto_header.length);
157
if (ret < 0) {
158
return ret;
159
}
160
diff --git a/block/qcow2.h b/block/qcow2.h
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow2.h
163
+++ b/block/qcow2.h
164
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
165
int64_t size);
166
int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
167
int64_t size);
168
+int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
169
+ void **refcount_table,
170
+ int64_t *refcount_table_size,
171
+ int64_t offset, int64_t size);
172
173
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
174
BlockDriverAmendStatusCB *status_cb,
175
--
176
1.8.3.1
177
178
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: John Snow <jsnow@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20170628120530.31251-10-vsementsov@virtuozzo.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/dirty-bitmap.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/dirty-bitmap.c
15
+++ b/block/dirty-bitmap.c
16
@@ -XXX,XX +XXX,XX @@ struct BdrvDirtyBitmap {
17
BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
18
char *name; /* Optional non-empty unique ID */
19
int64_t size; /* Size of the bitmap (Number of sectors) */
20
- bool disabled; /* Bitmap is read-only */
21
+ bool disabled; /* Bitmap is disabled. It ignores all writes to
22
+ the device */
23
int active_iterators; /* How many iterators are active */
24
QLIST_ENTRY(BdrvDirtyBitmap) list;
25
};
26
--
27
1.8.3.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add bs local variable to simplify code.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: John Snow <jsnow@redhat.com>
7
Message-id: 20170628120530.31251-13-vsementsov@virtuozzo.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block.c | 14 ++++++++------
11
1 file changed, 8 insertions(+), 6 deletions(-)
12
13
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
16
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ error:
18
void bdrv_reopen_commit(BDRVReopenState *reopen_state)
19
{
20
BlockDriver *drv;
21
+ BlockDriverState *bs;
22
23
assert(reopen_state != NULL);
24
- drv = reopen_state->bs->drv;
25
+ bs = reopen_state->bs;
26
+ drv = bs->drv;
27
assert(drv != NULL);
28
29
/* If there are any driver level actions to take */
30
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
31
}
32
33
/* set BDS specific flags now */
34
- QDECREF(reopen_state->bs->explicit_options);
35
+ QDECREF(bs->explicit_options);
36
37
- reopen_state->bs->explicit_options = reopen_state->explicit_options;
38
- reopen_state->bs->open_flags = reopen_state->flags;
39
- reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
40
+ bs->explicit_options = reopen_state->explicit_options;
41
+ bs->open_flags = reopen_state->flags;
42
+ bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
43
44
- bdrv_refresh_limits(reopen_state->bs, NULL);
45
+ bdrv_refresh_limits(bs, NULL);
46
}
47
48
/*
49
--
50
1.8.3.1
51
52
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Mirror AUTO flag from Qcow2 bitmap in BdrvDirtyBitmap. This will be
4
needed in future, to save this flag back to Qcow2 for persistent
5
bitmaps.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-id: 20170628120530.31251-16-vsementsov@virtuozzo.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/dirty-bitmap.c | 18 ++++++++++++++++++
12
block/qcow2-bitmap.c | 2 ++
13
include/block/dirty-bitmap.h | 2 ++
14
3 files changed, 22 insertions(+)
15
16
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/dirty-bitmap.c
19
+++ b/block/dirty-bitmap.c
20
@@ -XXX,XX +XXX,XX @@ struct BdrvDirtyBitmap {
21
Such operations must fail and both the image
22
and this bitmap must remain unchanged while
23
this flag is set. */
24
+ bool autoload; /* For persistent bitmaps: bitmap must be
25
+ autoloaded on image opening */
26
QLIST_ENTRY(BdrvDirtyBitmap) list;
27
};
28
29
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
30
assert(!bdrv_dirty_bitmap_frozen(bitmap));
31
g_free(bitmap->name);
32
bitmap->name = NULL;
33
+ bitmap->autoload = false;
34
}
35
36
/* Called with BQL taken. */
37
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
38
bitmap->name = NULL;
39
successor->name = name;
40
bitmap->successor = NULL;
41
+ successor->autoload = bitmap->autoload;
42
+ bitmap->autoload = false;
43
bdrv_release_dirty_bitmap(bs, bitmap);
44
45
return successor;
46
@@ -XXX,XX +XXX,XX @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs)
47
48
return false;
49
}
50
+
51
+/* Called with BQL taken. */
52
+void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload)
53
+{
54
+ qemu_mutex_lock(bitmap->mutex);
55
+ bitmap->autoload = autoload;
56
+ qemu_mutex_unlock(bitmap->mutex);
57
+}
58
+
59
+bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap)
60
+{
61
+ return bitmap->autoload;
62
+}
63
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/qcow2-bitmap.c
66
+++ b/block/qcow2-bitmap.c
67
@@ -XXX,XX +XXX,XX @@ bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
68
if (bitmap == NULL) {
69
goto fail;
70
}
71
+
72
+ bdrv_dirty_bitmap_set_autoload(bitmap, true);
73
bm->flags |= BME_FLAG_IN_USE;
74
created_dirty_bitmaps =
75
g_slist_append(created_dirty_bitmaps, bitmap);
76
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/block/dirty-bitmap.h
79
+++ b/include/block/dirty-bitmap.h
80
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap,
81
void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
82
83
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
84
+void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload);
85
86
/* Functions that require manual locking. */
87
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
88
@@ -XXX,XX +XXX,XX @@ int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap);
89
void bdrv_dirty_bitmap_truncate(BlockDriverState *bs);
90
bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
91
bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
92
+bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
93
94
#endif
95
--
96
1.8.3.1
97
98
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Release bitmaps after 'if (bs->drv) { ... }' block. This will allow
4
format driver to save persistent bitmaps, which will appear in following
5
commits.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20170628120530.31251-17-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block.c | 6 +++---
13
1 file changed, 3 insertions(+), 3 deletions(-)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
20
bdrv_flush(bs);
21
bdrv_drain(bs); /* in case flush left pending I/O */
22
23
- bdrv_release_named_dirty_bitmaps(bs);
24
- assert(QLIST_EMPTY(&bs->dirty_bitmaps));
25
-
26
if (bs->drv) {
27
BdrvChild *child, *next;
28
29
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
30
bs->full_open_options = NULL;
31
}
32
33
+ bdrv_release_named_dirty_bitmaps(bs);
34
+ assert(QLIST_EMPTY(&bs->dirty_bitmaps));
35
+
36
QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
37
g_free(ban);
38
}
39
--
40
1.8.3.1
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
New field BdrvDirtyBitmap.persistent means, that bitmap should be saved
4
by format driver in .bdrv_close and .bdrv_inactivate. No format driver
5
supports it for now.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-id: 20170628120530.31251-18-vsementsov@virtuozzo.com
9
[mreitz: Fixed indentation]
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/dirty-bitmap.c | 29 +++++++++++++++++++++++++++++
13
block/qcow2-bitmap.c | 1 +
14
include/block/dirty-bitmap.h | 4 ++++
15
3 files changed, 34 insertions(+)
16
17
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/dirty-bitmap.c
20
+++ b/block/dirty-bitmap.c
21
@@ -XXX,XX +XXX,XX @@ struct BdrvDirtyBitmap {
22
this flag is set. */
23
bool autoload; /* For persistent bitmaps: bitmap must be
24
autoloaded on image opening */
25
+ bool persistent; /* bitmap must be saved to owner disk image */
26
QLIST_ENTRY(BdrvDirtyBitmap) list;
27
};
28
29
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap)
30
assert(!bdrv_dirty_bitmap_frozen(bitmap));
31
g_free(bitmap->name);
32
bitmap->name = NULL;
33
+ bitmap->persistent = false;
34
bitmap->autoload = false;
35
}
36
37
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs,
38
bitmap->name = NULL;
39
successor->name = name;
40
bitmap->successor = NULL;
41
+ successor->persistent = bitmap->persistent;
42
+ bitmap->persistent = false;
43
successor->autoload = bitmap->autoload;
44
bitmap->autoload = false;
45
bdrv_release_dirty_bitmap(bs, bitmap);
46
@@ -XXX,XX +XXX,XX @@ bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap)
47
{
48
return bitmap->autoload;
49
}
50
+
51
+/* Called with BQL taken. */
52
+void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
53
+{
54
+ qemu_mutex_lock(bitmap->mutex);
55
+ bitmap->persistent = persistent;
56
+ qemu_mutex_unlock(bitmap->mutex);
57
+}
58
+
59
+bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
60
+{
61
+ return bitmap->persistent;
62
+}
63
+
64
+bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
65
+{
66
+ BdrvDirtyBitmap *bm;
67
+ QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
68
+ if (bm->persistent && !bm->readonly) {
69
+ return true;
70
+ }
71
+ }
72
+
73
+ return false;
74
+}
75
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/qcow2-bitmap.c
78
+++ b/block/qcow2-bitmap.c
79
@@ -XXX,XX +XXX,XX @@ bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp)
80
goto fail;
81
}
82
83
+ bdrv_dirty_bitmap_set_persistance(bitmap, true);
84
bdrv_dirty_bitmap_set_autoload(bitmap, true);
85
bm->flags |= BME_FLAG_IN_USE;
86
created_dirty_bitmaps =
87
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/include/block/dirty-bitmap.h
90
+++ b/include/block/dirty-bitmap.h
91
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap);
92
93
void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value);
94
void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload);
95
+void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap,
96
+ bool persistent);
97
98
/* Functions that require manual locking. */
99
void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap);
100
@@ -XXX,XX +XXX,XX @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs);
101
bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
102
bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
103
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
104
+bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
105
+bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
106
107
#endif
108
--
109
1.8.3.1
110
111
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
Reviewed-by: John Snow <jsnow@redhat.com>
6
Message-id: 20170628120530.31251-19-vsementsov@virtuozzo.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/dirty-bitmap.c | 7 +++++++
10
include/block/dirty-bitmap.h | 2 ++
11
2 files changed, 9 insertions(+)
12
13
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/dirty-bitmap.c
16
+++ b/block/dirty-bitmap.c
17
@@ -XXX,XX +XXX,XX @@ bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
18
19
return false;
20
}
21
+
22
+BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
23
+ BdrvDirtyBitmap *bitmap)
24
+{
25
+ return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) :
26
+ QLIST_NEXT(bitmap, list);
27
+}
28
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/block/dirty-bitmap.h
31
+++ b/include/block/dirty-bitmap.h
32
@@ -XXX,XX +XXX,XX @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
33
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
34
bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
35
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
36
+BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
37
+ BdrvDirtyBitmap *bitmap);
38
39
#endif
40
--
41
1.8.3.1
42
43
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Store bitmaps and mark them read-only on reopening image as read-only.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20170628120530.31251-21-vsementsov@virtuozzo.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/qcow2-bitmap.c | 22 ++++++++++++++++++++++
11
block/qcow2.c | 5 +++++
12
block/qcow2.h | 1 +
13
3 files changed, 28 insertions(+)
14
15
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2-bitmap.c
18
+++ b/block/qcow2-bitmap.c
19
@@ -XXX,XX +XXX,XX @@ fail:
20
21
bitmap_list_free(bm_list);
22
}
23
+
24
+int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp)
25
+{
26
+ BdrvDirtyBitmap *bitmap;
27
+ Error *local_err = NULL;
28
+
29
+ qcow2_store_persistent_dirty_bitmaps(bs, &local_err);
30
+ if (local_err != NULL) {
31
+ error_propagate(errp, local_err);
32
+ return -EINVAL;
33
+ }
34
+
35
+ for (bitmap = bdrv_dirty_bitmap_next(bs, NULL); bitmap != NULL;
36
+ bitmap = bdrv_dirty_bitmap_next(bs, bitmap))
37
+ {
38
+ if (bdrv_dirty_bitmap_get_persistance(bitmap)) {
39
+ bdrv_dirty_bitmap_set_readonly(bitmap, true);
40
+ }
41
+ }
42
+
43
+ return 0;
44
+}
45
diff --git a/block/qcow2.c b/block/qcow2.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2.c
48
+++ b/block/qcow2.c
49
@@ -XXX,XX +XXX,XX @@ static int qcow2_reopen_prepare(BDRVReopenState *state,
50
51
/* We need to write out any unwritten data if we reopen read-only. */
52
if ((state->flags & BDRV_O_RDWR) == 0) {
53
+ ret = qcow2_reopen_bitmaps_ro(state->bs, errp);
54
+ if (ret < 0) {
55
+ goto fail;
56
+ }
57
+
58
ret = bdrv_flush(state->bs);
59
if (ret < 0) {
60
goto fail;
61
diff --git a/block/qcow2.h b/block/qcow2.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block/qcow2.h
64
+++ b/block/qcow2.h
65
@@ -XXX,XX +XXX,XX @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
66
bool qcow2_load_autoloading_dirty_bitmaps(BlockDriverState *bs, Error **errp);
67
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
68
void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp);
69
+int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
70
71
#endif
72
--
73
1.8.3.1
74
75
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This will be needed to check some restrictions before making bitmap
4
persistent in qmp-block-dirty-bitmap-add (this functionality will be
5
added by future patch)
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Message-id: 20170628120530.31251-22-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block.c | 22 ++++++++++++++++++++++
14
include/block/block.h | 3 +++
15
include/block/block_int.h | 4 ++++
16
3 files changed, 29 insertions(+)
17
18
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
23
24
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
25
}
26
+
27
+bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
28
+ uint32_t granularity, Error **errp)
29
+{
30
+ BlockDriver *drv = bs->drv;
31
+
32
+ if (!drv) {
33
+ error_setg_errno(errp, ENOMEDIUM,
34
+ "Can't store persistent bitmaps to %s",
35
+ bdrv_get_device_or_node_name(bs));
36
+ return false;
37
+ }
38
+
39
+ if (!drv->bdrv_can_store_new_dirty_bitmap) {
40
+ error_setg_errno(errp, ENOTSUP,
41
+ "Can't store persistent bitmaps to %s",
42
+ bdrv_get_device_or_node_name(bs));
43
+ return false;
44
+ }
45
+
46
+ return drv->bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp);
47
+}
48
diff --git a/include/block/block.h b/include/block/block.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block.h
51
+++ b/include/block/block.h
52
@@ -XXX,XX +XXX,XX @@ void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child,
53
Error **errp);
54
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
55
56
+bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
57
+ uint32_t granularity, Error **errp);
58
+
59
#endif
60
diff --git a/include/block/block_int.h b/include/block/block_int.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/include/block/block_int.h
63
+++ b/include/block/block_int.h
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
65
* field of BlockDirtyBitmap's in case of success.
66
*/
67
int (*bdrv_reopen_bitmaps_rw)(BlockDriverState *bs, Error **errp);
68
+ bool (*bdrv_can_store_new_dirty_bitmap)(BlockDriverState *bs,
69
+ const char *name,
70
+ uint32_t granularity,
71
+ Error **errp);
72
73
QLIST_ENTRY(BlockDriver) list;
74
};
75
--
76
1.8.3.1
77
78
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add optional 'persistent' flag to qmp command block-dirty-bitmap-add.
4
Default is false.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Denis V. Lunev <den@openvz.org>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Message-id: 20170628120530.31251-24-vsementsov@virtuozzo.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
blockdev.c | 18 +++++++++++++++++-
14
qapi/block-core.json | 8 +++++++-
15
2 files changed, 24 insertions(+), 2 deletions(-)
16
17
diff --git a/blockdev.c b/blockdev.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/blockdev.c
20
+++ b/blockdev.c
21
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
22
/* AIO context taken and released within qmp_block_dirty_bitmap_add */
23
qmp_block_dirty_bitmap_add(action->node, action->name,
24
action->has_granularity, action->granularity,
25
+ action->has_persistent, action->persistent,
26
&local_err);
27
28
if (!local_err) {
29
@@ -XXX,XX +XXX,XX @@ out:
30
31
void qmp_block_dirty_bitmap_add(const char *node, const char *name,
32
bool has_granularity, uint32_t granularity,
33
+ bool has_persistent, bool persistent,
34
Error **errp)
35
{
36
BlockDriverState *bs;
37
+ BdrvDirtyBitmap *bitmap;
38
39
if (!name || name[0] == '\0') {
40
error_setg(errp, "Bitmap name cannot be empty");
41
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
42
granularity = bdrv_get_default_bitmap_granularity(bs);
43
}
44
45
- bdrv_create_dirty_bitmap(bs, granularity, name, errp);
46
+ if (!has_persistent) {
47
+ persistent = false;
48
+ }
49
+
50
+ if (persistent &&
51
+ !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
52
+ {
53
+ return;
54
+ }
55
+
56
+ bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
57
+ if (bitmap != NULL) {
58
+ bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
59
+ }
60
}
61
62
void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
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
# @granularity: the bitmap granularity, default is 64k for
69
# block-dirty-bitmap-add
70
#
71
+# @persistent: the bitmap is persistent, i.e. it will be saved to the
72
+# corresponding block device image file on its close. For now only
73
+# Qcow2 disks support persistent bitmaps. Default is false for
74
+# block-dirty-bitmap-add. (Since: 2.10)
75
+#
76
# Since: 2.4
77
##
78
{ 'struct': 'BlockDirtyBitmapAdd',
79
- 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32' } }
80
+ 'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
81
+ '*persistent': 'bool' } }
82
83
##
84
# @block-dirty-bitmap-add:
85
--
86
1.8.3.1
87
88
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Optional. Default is false.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Denis V. Lunev <den@openvz.org>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: 20170628120530.31251-25-vsementsov@virtuozzo.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
blockdev.c | 18 ++++++++++++++++--
13
qapi/block-core.json | 6 +++++-
14
2 files changed, 21 insertions(+), 3 deletions(-)
15
16
diff --git a/blockdev.c b/blockdev.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/blockdev.c
19
+++ b/blockdev.c
20
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_add_prepare(BlkActionState *common,
21
qmp_block_dirty_bitmap_add(action->node, action->name,
22
action->has_granularity, action->granularity,
23
action->has_persistent, action->persistent,
24
+ action->has_autoload, action->autoload,
25
&local_err);
26
27
if (!local_err) {
28
@@ -XXX,XX +XXX,XX @@ out:
29
void qmp_block_dirty_bitmap_add(const char *node, const char *name,
30
bool has_granularity, uint32_t granularity,
31
bool has_persistent, bool persistent,
32
+ bool has_autoload, bool autoload,
33
Error **errp)
34
{
35
BlockDriverState *bs;
36
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
37
if (!has_persistent) {
38
persistent = false;
39
}
40
+ if (!has_autoload) {
41
+ autoload = false;
42
+ }
43
+
44
+ if (has_autoload && !persistent) {
45
+ error_setg(errp, "Autoload flag must be used only for persistent "
46
+ "bitmaps");
47
+ return;
48
+ }
49
50
if (persistent &&
51
!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
52
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
53
}
54
55
bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
56
- if (bitmap != NULL) {
57
- bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
58
+ if (bitmap == NULL) {
59
+ return;
60
}
61
+
62
+ bdrv_dirty_bitmap_set_persistance(bitmap, persistent);
63
+ bdrv_dirty_bitmap_set_autoload(bitmap, autoload);
64
}
65
66
void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
67
diff --git a/qapi/block-core.json b/qapi/block-core.json
68
index XXXXXXX..XXXXXXX 100644
69
--- a/qapi/block-core.json
70
+++ b/qapi/block-core.json
71
@@ -XXX,XX +XXX,XX @@
72
# Qcow2 disks support persistent bitmaps. Default is false for
73
# block-dirty-bitmap-add. (Since: 2.10)
74
#
75
+# @autoload: the bitmap will be automatically loaded when the image it is stored
76
+# in is opened. This flag may only be specified for persistent
77
+# bitmaps. Default is false for block-dirty-bitmap-add. (Since: 2.10)
78
+#
79
# Since: 2.4
80
##
81
{ 'struct': 'BlockDirtyBitmapAdd',
82
'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
83
- '*persistent': 'bool' } }
84
+ '*persistent': 'bool', '*autoload': 'bool' } }
85
86
##
87
# @block-dirty-bitmap-add:
88
--
89
1.8.3.1
90
91
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
Message-id: 20170628120530.31251-26-vsementsov@virtuozzo.com
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
7
block/dirty-bitmap.c | 5 +++++
8
blockdev.c | 25 +++++++++++++++++++++++++
9
include/block/dirty-bitmap.h | 1 +
10
include/qemu/hbitmap.h | 8 ++++++++
11
qapi/block-core.json | 27 +++++++++++++++++++++++++++
12
tests/Makefile.include | 2 +-
13
util/hbitmap.c | 11 +++++++++++
14
7 files changed, 78 insertions(+), 1 deletion(-)
15
16
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/dirty-bitmap.c
19
+++ b/block/dirty-bitmap.c
20
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
21
return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) :
22
QLIST_NEXT(bitmap, list);
23
}
24
+
25
+char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp)
26
+{
27
+ return hbitmap_sha256(bitmap->bitmap, errp);
28
+}
29
diff --git a/blockdev.c b/blockdev.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/blockdev.c
32
+++ b/blockdev.c
33
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
34
bdrv_clear_dirty_bitmap(bitmap, NULL);
35
}
36
37
+BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
38
+ const char *name,
39
+ Error **errp)
40
+{
41
+ BdrvDirtyBitmap *bitmap;
42
+ BlockDriverState *bs;
43
+ BlockDirtyBitmapSha256 *ret = NULL;
44
+ char *sha256;
45
+
46
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
47
+ if (!bitmap || !bs) {
48
+ return NULL;
49
+ }
50
+
51
+ sha256 = bdrv_dirty_bitmap_sha256(bitmap, errp);
52
+ if (sha256 == NULL) {
53
+ return NULL;
54
+ }
55
+
56
+ ret = g_new(BlockDirtyBitmapSha256, 1);
57
+ ret->sha256 = sha256;
58
+
59
+ return ret;
60
+}
61
+
62
void hmp_drive_del(Monitor *mon, const QDict *qdict)
63
{
64
const char *id = qdict_get_str(qdict, "id");
65
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/dirty-bitmap.h
68
+++ b/include/block/dirty-bitmap.h
69
@@ -XXX,XX +XXX,XX @@ bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
70
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
71
BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
72
BdrvDirtyBitmap *bitmap);
73
+char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp);
74
75
#endif
76
diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/qemu/hbitmap.h
79
+++ b/include/qemu/hbitmap.h
80
@@ -XXX,XX +XXX,XX @@ void hbitmap_deserialize_ones(HBitmap *hb, uint64_t start, uint64_t count,
81
void hbitmap_deserialize_finish(HBitmap *hb);
82
83
/**
84
+ * hbitmap_sha256:
85
+ * @bitmap: HBitmap to operate on.
86
+ *
87
+ * Returns SHA256 hash of the last level.
88
+ */
89
+char *hbitmap_sha256(const HBitmap *bitmap, Error **errp);
90
+
91
+/**
92
* hbitmap_free:
93
* @hb: HBitmap to operate on.
94
*
95
diff --git a/qapi/block-core.json b/qapi/block-core.json
96
index XXXXXXX..XXXXXXX 100644
97
--- a/qapi/block-core.json
98
+++ b/qapi/block-core.json
99
@@ -XXX,XX +XXX,XX @@
100
'data': 'BlockDirtyBitmap' }
101
102
##
103
+# @BlockDirtyBitmapSha256:
104
+#
105
+# SHA256 hash of dirty bitmap data
106
+#
107
+# @sha256: ASCII representation of SHA256 bitmap hash
108
+#
109
+# Since: 2.10
110
+##
111
+ { 'struct': 'BlockDirtyBitmapSha256',
112
+ 'data': {'sha256': 'str'} }
113
+
114
+##
115
+# @x-debug-block-dirty-bitmap-sha256:
116
+#
117
+# Get bitmap SHA256
118
+#
119
+# Returns: BlockDirtyBitmapSha256 on success
120
+# If @node is not a valid block device, DeviceNotFound
121
+# If @name is not found or if hashing has failed, GenericError with an
122
+# explanation
123
+#
124
+# Since: 2.10
125
+##
126
+ { 'command': 'x-debug-block-dirty-bitmap-sha256',
127
+ 'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' }
128
+
129
+##
130
# @blockdev-mirror:
131
#
132
# Start mirroring a block device's writes to a new destination.
133
diff --git a/tests/Makefile.include b/tests/Makefile.include
134
index XXXXXXX..XXXXXXX 100644
135
--- a/tests/Makefile.include
136
+++ b/tests/Makefile.include
137
@@ -XXX,XX +XXX,XX @@ tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-u
138
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
139
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
140
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
141
-tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y)
142
+tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y)
143
tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
144
tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y)
145
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
146
diff --git a/util/hbitmap.c b/util/hbitmap.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/util/hbitmap.c
149
+++ b/util/hbitmap.c
150
@@ -XXX,XX +XXX,XX @@
151
#include "qemu/hbitmap.h"
152
#include "qemu/host-utils.h"
153
#include "trace.h"
154
+#include "crypto/hash.h"
155
156
/* HBitmaps provides an array of bits. The bits are stored as usual in an
157
* array of unsigned longs, but HBitmap is also optimized to provide fast
158
@@ -XXX,XX +XXX,XX @@ void hbitmap_free_meta(HBitmap *hb)
159
hbitmap_free(hb->meta);
160
hb->meta = NULL;
161
}
162
+
163
+char *hbitmap_sha256(const HBitmap *bitmap, Error **errp)
164
+{
165
+ size_t size = bitmap->sizes[HBITMAP_LEVELS - 1] * sizeof(unsigned long);
166
+ char *data = (char *)bitmap->levels[HBITMAP_LEVELS - 1];
167
+ char *hash = NULL;
168
+ qcrypto_hash_digest(QCRYPTO_HASH_ALG_SHA256, data, size, &hash, errp);
169
+
170
+ return hash;
171
+}
172
--
173
1.8.3.1
174
175
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: 20170628120530.31251-27-vsementsov@virtuozzo.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/165 | 105 +++++++++++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/165.out | 5 +++
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 111 insertions(+)
12
create mode 100755 tests/qemu-iotests/165
13
create mode 100644 tests/qemu-iotests/165.out
14
15
diff --git a/tests/qemu-iotests/165 b/tests/qemu-iotests/165
16
new file mode 100755
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/qemu-iotests/165
20
@@ -XXX,XX +XXX,XX @@
21
+#!/usr/bin/env python
22
+#
23
+# Tests for persistent dirty bitmaps.
24
+#
25
+# Copyright: Vladimir Sementsov-Ogievskiy 2015-2017
26
+#
27
+# This program is free software; you can redistribute it and/or modify
28
+# it under the terms of the GNU General Public License as published by
29
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
31
+#
32
+# This program is distributed in the hope that it will be useful,
33
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+# GNU General Public License for more details.
36
+#
37
+# You should have received a copy of the GNU General Public License
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
40
+
41
+import os
42
+import re
43
+import iotests
44
+from iotests import qemu_img
45
+
46
+disk = os.path.join(iotests.test_dir, 'disk')
47
+disk_size = 0x40000000 # 1G
48
+
49
+# regions for qemu_io: (start, count) in bytes
50
+regions1 = ((0, 0x100000),
51
+ (0x200000, 0x100000))
52
+
53
+regions2 = ((0x10000000, 0x20000),
54
+ (0x3fff0000, 0x10000))
55
+
56
+class TestPersistentDirtyBitmap(iotests.QMPTestCase):
57
+
58
+ def setUp(self):
59
+ qemu_img('create', '-f', iotests.imgfmt, disk, str(disk_size))
60
+
61
+ def tearDown(self):
62
+ os.remove(disk)
63
+
64
+ def mkVm(self):
65
+ return iotests.VM().add_drive(disk)
66
+
67
+ def mkVmRo(self):
68
+ return iotests.VM().add_drive(disk, opts='readonly=on')
69
+
70
+ def getSha256(self):
71
+ result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256',
72
+ node='drive0', name='bitmap0')
73
+ return result['return']['sha256']
74
+
75
+ def checkBitmap(self, sha256):
76
+ result = self.vm.qmp('x-debug-block-dirty-bitmap-sha256',
77
+ node='drive0', name='bitmap0')
78
+ self.assert_qmp(result, 'return/sha256', sha256);
79
+
80
+ def writeRegions(self, regions):
81
+ for r in regions:
82
+ self.vm.hmp_qemu_io('drive0',
83
+ 'write %d %d' % r)
84
+
85
+ def qmpAddBitmap(self):
86
+ self.vm.qmp('block-dirty-bitmap-add', node='drive0',
87
+ name='bitmap0', persistent=True, autoload=True)
88
+
89
+ def test_persistent(self):
90
+ self.vm = self.mkVm()
91
+ self.vm.launch()
92
+ self.qmpAddBitmap()
93
+
94
+ self.writeRegions(regions1)
95
+ sha256 = self.getSha256()
96
+
97
+ self.vm.shutdown()
98
+
99
+ self.vm = self.mkVmRo()
100
+ self.vm.launch()
101
+ self.vm.shutdown()
102
+
103
+ #catch 'Persistent bitmaps are lost' possible error
104
+ log = self.vm.get_log()
105
+ log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
106
+ log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
107
+ if log:
108
+ print log
109
+
110
+ self.vm = self.mkVm()
111
+ self.vm.launch()
112
+
113
+ self.checkBitmap(sha256)
114
+ self.writeRegions(regions2)
115
+ sha256 = self.getSha256()
116
+
117
+ self.vm.shutdown()
118
+ self.vm.launch()
119
+
120
+ self.checkBitmap(sha256)
121
+
122
+ self.vm.shutdown()
123
+
124
+if __name__ == '__main__':
125
+ iotests.main(supported_fmts=['qcow2'])
126
diff --git a/tests/qemu-iotests/165.out b/tests/qemu-iotests/165.out
127
new file mode 100644
128
index XXXXXXX..XXXXXXX
129
--- /dev/null
130
+++ b/tests/qemu-iotests/165.out
131
@@ -XXX,XX +XXX,XX @@
132
+.
133
+----------------------------------------------------------------------
134
+Ran 1 tests
135
+
136
+OK
137
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
138
index XXXXXXX..XXXXXXX 100644
139
--- a/tests/qemu-iotests/group
140
+++ b/tests/qemu-iotests/group
141
@@ -XXX,XX +XXX,XX @@
142
159 rw auto quick
143
160 rw auto quick
144
162 auto quick
145
+165 rw auto quick
146
170 rw auto quick
147
171 rw auto quick
148
172 auto
149
--
150
1.8.3.1
151
152
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Interface for removing persistent bitmap from its storage.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20170628120530.31251-28-vsementsov@virtuozzo.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/dirty-bitmap.c | 18 ++++++++++++++++++
12
include/block/block_int.h | 3 +++
13
include/block/dirty-bitmap.h | 3 +++
14
3 files changed, 24 insertions(+)
15
16
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/dirty-bitmap.c
19
+++ b/block/dirty-bitmap.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
21
/**
22
* Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()).
23
* There must not be any frozen bitmaps attached.
24
+ * This function does not remove persistent bitmaps from the storage.
25
* Called with BQL taken.
26
*/
27
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
28
@@ -XXX,XX +XXX,XX @@ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
29
bdrv_do_release_matching_dirty_bitmap(bs, NULL, true);
30
}
31
32
+/**
33
+ * Remove persistent dirty bitmap from the storage if it exists.
34
+ * Absence of bitmap is not an error, because we have the following scenario:
35
+ * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
36
+ * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should
37
+ * not fail.
38
+ * This function doesn't release corresponding BdrvDirtyBitmap.
39
+ */
40
+void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
41
+ const char *name,
42
+ Error **errp)
43
+{
44
+ if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) {
45
+ bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp);
46
+ }
47
+}
48
+
49
/* Called with BQL taken. */
50
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap)
51
{
52
diff --git a/include/block/block_int.h b/include/block/block_int.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/include/block/block_int.h
55
+++ b/include/block/block_int.h
56
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
57
const char *name,
58
uint32_t granularity,
59
Error **errp);
60
+ void (*bdrv_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
61
+ const char *name,
62
+ Error **errp);
63
64
QLIST_ENTRY(BlockDriver) list;
65
};
66
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
67
index XXXXXXX..XXXXXXX 100644
68
--- a/include/block/dirty-bitmap.h
69
+++ b/include/block/dirty-bitmap.h
70
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
71
void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap);
72
void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
73
void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
74
+void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
75
+ const char *name,
76
+ Error **errp);
77
void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
78
void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap);
79
BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs);
80
--
81
1.8.3.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
While the qemu-img dd command does accept --image-opts
4
this is not sufficient to make it work with the LUKS
5
image yet. This is because bdrv_create() still always
6
requires the non-image-opts syntax.
7
8
Thus we must skip 159/170 with luks for now
9
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
13
Message-id: 20170626123510.20134-2-berrange@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/159 | 1 +
17
tests/qemu-iotests/170 | 1 +
18
2 files changed, 2 insertions(+)
19
20
diff --git a/tests/qemu-iotests/159 b/tests/qemu-iotests/159
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/159
23
+++ b/tests/qemu-iotests/159
24
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
25
_supported_fmt generic
26
_supported_proto file
27
_supported_os Linux
28
+_unsupported_fmt luks
29
30
TEST_SIZES="5 512 1024 1999 1K 64K 1M"
31
32
diff --git a/tests/qemu-iotests/170 b/tests/qemu-iotests/170
33
index XXXXXXX..XXXXXXX 100755
34
--- a/tests/qemu-iotests/170
35
+++ b/tests/qemu-iotests/170
36
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
37
_supported_fmt generic
38
_supported_proto file
39
_supported_os Linux
40
+_unsupported_fmt luks
41
42
echo
43
echo "== Creating image =="
44
--
45
1.8.3.1
46
47
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
The tests 033, 140, 145 and 157 were all broken
4
when run with LUKS, since they did not correctly use
5
the required image opts args syntax to specify the
6
decryption secret. Further, the 120 test simply does
7
not make sense to run with luks, as the scenario
8
exercised is not relevant.
9
10
The test 181 was broken when run with LUKS because
11
it didn't take account of fact that $TEST_IMG was
12
already in image opts syntax. The launch_qemu
13
helper also didn't register the secret object
14
providing the LUKS password.
15
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
18
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
19
Message-id: 20170626123510.20134-3-berrange@redhat.com
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
tests/qemu-iotests/033 | 12 ++++++++++--
23
tests/qemu-iotests/120 | 1 +
24
tests/qemu-iotests/140 | 9 ++++++++-
25
tests/qemu-iotests/145 | 19 +++++++++++++++++--
26
tests/qemu-iotests/157 | 17 ++++++++++++++---
27
tests/qemu-iotests/157.out | 16 ++++++++--------
28
tests/qemu-iotests/174 | 2 +-
29
tests/qemu-iotests/181 | 21 ++++++++++++++++-----
30
tests/qemu-iotests/common.qemu | 9 +++++++--
31
9 files changed, 82 insertions(+), 24 deletions(-)
32
33
diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033
34
index XXXXXXX..XXXXXXX 100755
35
--- a/tests/qemu-iotests/033
36
+++ b/tests/qemu-iotests/033
37
@@ -XXX,XX +XXX,XX @@ do_test()
38
    local align=$1
39
    local iocmd=$2
40
    local img=$3
41
+    if [ "$IMGOPTSSYNTAX" = "true" ]
42
+    then
43
+     IO_OPEN_ARG="$img"
44
+     IO_EXTRA_ARGS="--image-opts"
45
+    else
46
+     IO_OPEN_ARG="-o driver=$IMGFMT,file.align=$align blkdebug::$img"
47
+     IO_EXTRA_ARGS=""
48
+    fi
49
    {
50
-        echo "open -o driver=$IMGFMT,file.align=$align blkdebug::$img"
51
+        echo "open $IO_OPEN_ARG"
52
        echo $iocmd
53
-    } | $QEMU_IO
54
+    } | $QEMU_IO $IO_EXTRA_ARGS
55
}
56
57
for write_zero_cmd in "write -z" "aio_write -z"; do
58
diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120
59
index XXXXXXX..XXXXXXX 100755
60
--- a/tests/qemu-iotests/120
61
+++ b/tests/qemu-iotests/120
62
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
63
_supported_fmt generic
64
_supported_proto file
65
_supported_os Linux
66
+_unsupported_fmt luks
67
68
_make_test_img 64M
69
70
diff --git a/tests/qemu-iotests/140 b/tests/qemu-iotests/140
71
index XXXXXXX..XXXXXXX 100755
72
--- a/tests/qemu-iotests/140
73
+++ b/tests/qemu-iotests/140
74
@@ -XXX,XX +XXX,XX @@ _make_test_img 64k
75
76
$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
77
78
+if test "$IMGOPTSSYNTAX" = "true"
79
+then
80
+ SYSEMU_DRIVE_ARG=if=none,media=cdrom,id=drv,"$TEST_IMG"
81
+else
82
+ SYSEMU_DRIVE_ARG=if=none,media=cdrom,id=drv,file="$TEST_IMG",driver=$IMGFMT
83
+fi
84
+
85
keep_stderr=y \
86
-_launch_qemu -drive if=none,media=cdrom,id=drv,file="$TEST_IMG",format=$IMGFMT \
87
+_launch_qemu -drive $SYSEMU_DRIVE_ARG \
88
2> >(_filter_nbd)
89
90
_send_qemu_cmd $QEMU_HANDLE \
91
diff --git a/tests/qemu-iotests/145 b/tests/qemu-iotests/145
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/145
94
+++ b/tests/qemu-iotests/145
95
@@ -XXX,XX +XXX,XX @@ _supported_proto generic
96
_supported_os Linux
97
98
_make_test_img 1M
99
-echo quit | $QEMU -nographic -hda "$TEST_IMG" -incoming 'exec:true' -snapshot -serial none -monitor stdio |
100
- _filter_qemu | _filter_hmp
101
+
102
+if test "$IMGOPTSSYNTAX" = "true"
103
+then
104
+ SYSEMU_DRIVE_ARG=if=none,$TEST_IMG
105
+ SYSEMU_EXTRA_ARGS=""
106
+ if [ -n "$IMGKEYSECRET" ]; then
107
+ SECRET_ARG="secret,id=keysec0,data=$IMGKEYSECRET"
108
+ SYSEMU_EXTRA_ARGS="-object $SECRET_ARG"
109
+ fi
110
+else
111
+ SYSEMU_DRIVE_ARG=if=none,file="$TEST_IMG",driver=$IMGFMT
112
+ SYSEMU_EXTRA_ARGS=""
113
+fi
114
+
115
+echo quit | $QEMU -nographic $SYSEMU_EXTRA_ARGS -drive $SYSEMU_DRIVE_ARG \
116
+ -incoming 'exec:true' -snapshot -serial none -monitor stdio \
117
+ | _filter_qemu | _filter_hmp
118
119
# success, all done
120
echo "*** done"
121
diff --git a/tests/qemu-iotests/157 b/tests/qemu-iotests/157
122
index XXXXXXX..XXXXXXX 100755
123
--- a/tests/qemu-iotests/157
124
+++ b/tests/qemu-iotests/157
125
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
126
127
function do_run_qemu()
128
{
129
- echo Testing: "$@"
130
(
131
if ! test -t 0; then
132
while read cmd; do
133
@@ -XXX,XX +XXX,XX @@ function run_qemu()
134
135
136
size=128M
137
-drive="if=none,file=$TEST_IMG,driver=$IMGFMT"
138
+if test "$IMGOPTSSYNTAX" = "true"
139
+then
140
+ SYSEMU_DRIVE_ARG=if=none,$TEST_IMG
141
+ SYSEMU_EXTRA_ARGS=""
142
+ if [ -n "$IMGKEYSECRET" ]; then
143
+ SECRET_ARG="secret,id=keysec0,data=$IMGKEYSECRET"
144
+ SYSEMU_EXTRA_ARGS="-object $SECRET_ARG"
145
+ fi
146
+else
147
+ SYSEMU_DRIVE_ARG=if=none,file="$TEST_IMG",driver=$IMGFMT
148
+ SYSEMU_EXTRA_ARGS=""
149
+fi
150
151
_make_test_img $size
152
153
@@ -XXX,XX +XXX,XX @@ echo
154
155
for cache in "writeback" "writethrough"; do
156
for wce in "" ",write-cache=auto" ",write-cache=on" ",write-cache=off"; do
157
+ echo "Testing: cache='$cache' wce='$wce'"
158
echo "info block" \
159
- | run_qemu -drive "$drive,cache=$cache" \
160
+ | run_qemu $SYSEMU_EXTRA_ARGS -drive "$SYSEMU_DRIVE_ARG,cache=$cache" \
161
-device "virtio-blk,drive=none0$wce" \
162
| grep -e "Testing" -e "Cache mode"
163
done
164
diff --git a/tests/qemu-iotests/157.out b/tests/qemu-iotests/157.out
165
index XXXXXXX..XXXXXXX 100644
166
--- a/tests/qemu-iotests/157.out
167
+++ b/tests/qemu-iotests/157.out
168
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
169
170
=== Setting WCE with qdev and with manually created BB ===
171
172
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0
173
+Testing: cache='writeback' wce=''
174
Cache mode: writeback
175
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=auto
176
+Testing: cache='writeback' wce=',write-cache=auto'
177
Cache mode: writeback
178
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=on
179
+Testing: cache='writeback' wce=',write-cache=on'
180
Cache mode: writeback
181
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writeback -device virtio-blk,drive=none0,write-cache=off
182
+Testing: cache='writeback' wce=',write-cache=off'
183
Cache mode: writethrough
184
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0
185
+Testing: cache='writethrough' wce=''
186
Cache mode: writethrough
187
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=auto
188
+Testing: cache='writethrough' wce=',write-cache=auto'
189
Cache mode: writethrough
190
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=on
191
+Testing: cache='writethrough' wce=',write-cache=on'
192
Cache mode: writeback
193
-Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,driver=IMGFMT,cache=writethrough -device virtio-blk,drive=none0,write-cache=off
194
+Testing: cache='writethrough' wce=',write-cache=off'
195
Cache mode: writethrough
196
*** done
197
diff --git a/tests/qemu-iotests/174 b/tests/qemu-iotests/174
198
index XXXXXXX..XXXXXXX 100755
199
--- a/tests/qemu-iotests/174
200
+++ b/tests/qemu-iotests/174
201
@@ -XXX,XX +XXX,XX @@ _unsupported_fmt raw
202
203
204
size=256K
205
-IMGFMT=raw IMGOPTS= _make_test_img $size | _filter_imgfmt
206
+IMGFMT=raw IMGKEYSECRET= IMGOPTS= _make_test_img $size | _filter_imgfmt
207
208
echo
209
echo "== reading wrong format should fail =="
210
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
211
index XXXXXXX..XXXXXXX 100755
212
--- a/tests/qemu-iotests/181
213
+++ b/tests/qemu-iotests/181
214
@@ -XXX,XX +XXX,XX @@ echo
215
216
qemu_comm_method="monitor"
217
218
-_launch_qemu \
219
- -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk
220
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
221
+ _launch_qemu \
222
+ -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk
223
+else
224
+ _launch_qemu \
225
+ -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk
226
+fi
227
src=$QEMU_HANDLE
228
229
-_launch_qemu \
230
- -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \
231
- -incoming "unix:${MIG_SOCKET}"
232
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
233
+ _launch_qemu \
234
+ -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk \
235
+ -incoming "unix:${MIG_SOCKET}"
236
+else
237
+ _launch_qemu \
238
+ -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \
239
+ -incoming "unix:${MIG_SOCKET}"
240
+fi
241
dest=$QEMU_HANDLE
242
243
echo
244
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
245
index XXXXXXX..XXXXXXX 100644
246
--- a/tests/qemu-iotests/common.qemu
247
+++ b/tests/qemu-iotests/common.qemu
248
@@ -XXX,XX +XXX,XX @@ function _launch_qemu()
249
mkfifo "${fifo_out}"
250
mkfifo "${fifo_in}"
251
252
+ object_options=
253
+ if [ -n "$IMGKEYSECRET" ]; then
254
+ object_options="--object secret,id=keysec0,data=$IMGKEYSECRET"
255
+ fi
256
+
257
if [ -z "$keep_stderr" ]; then
258
QEMU_NEED_PID='y'\
259
- ${QEMU} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \
260
+ ${QEMU} ${object_options} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \
261
2>&1 \
262
<"${fifo_in}" &
263
elif [ "$keep_stderr" = "y" ]; then
264
QEMU_NEED_PID='y'\
265
- ${QEMU} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \
266
+ ${QEMU} ${object_options} -nographic -serial none ${comm} "${@}" >"${fifo_out}" \
267
<"${fifo_in}" &
268
else
269
exit 1
270
--
271
1.8.3.1
272
273
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
By default the PBKDF algorithm used with LUKS is tuned
4
based on the number of iterations to produce 1 second
5
of running time. This makes running the I/O test with
6
the LUKS format orders of magnitude slower than with
7
qcow2/raw formats.
8
9
When creating LUKS images, set the iteration time to
10
a 10ms to reduce the time overhead for LUKS, since
11
security does not matter in I/O tests.
12
13
Previously a full 'check -luks' would take
14
15
$ time ./check -luks
16
Passed all 22 tests
17
18
real 23m9.988s
19
user 21m46.223s
20
sys 0m22.841s
21
22
Now it takes
23
24
$ time ./check -luks
25
Passed all 22 tests
26
27
real 4m39.235s
28
user 3m29.590s
29
sys 0m24.234s
30
31
Still slow compared to qcow2/raw, but much improved
32
none the less.
33
34
Reviewed-by: Max Reitz <mreitz@redhat.com>
35
Reviewed-by: Eric Blake <eblake@redhat.com>
36
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
37
Message-id: 20170626123510.20134-4-berrange@redhat.com
38
Signed-off-by: Max Reitz <mreitz@redhat.com>
39
---
40
tests/qemu-iotests/149 | 3 +
41
tests/qemu-iotests/149.out | 118 +++++++++++++++++++--------------------
42
tests/qemu-iotests/common.filter | 3 +-
43
tests/qemu-iotests/common.rc | 3 +
44
4 files changed, 67 insertions(+), 60 deletions(-)
45
46
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
47
index XXXXXXX..XXXXXXX 100755
48
--- a/tests/qemu-iotests/149
49
+++ b/tests/qemu-iotests/149
50
@@ -XXX,XX +XXX,XX @@ def cryptsetup_add_password(config, slot):
51
args = ["luksAddKey", config.image_path(),
52
"--key-slot", slot,
53
"--key-file", "-",
54
+ "--iter-time", "10",
55
pwfile]
56
57
cryptsetup(args, password)
58
@@ -XXX,XX +XXX,XX @@ def cryptsetup_format(config):
59
args.extend(["--hash", config.hash])
60
args.extend(["--key-slot", slot])
61
args.extend(["--key-file", "-"])
62
+ args.extend(["--iter-time", "10"])
63
args.append(config.image_path())
64
65
cryptsetup(args, password)
66
@@ -XXX,XX +XXX,XX @@ def qemu_img_create(config, size_mb):
67
68
opts = [
69
"key-secret=sec0",
70
+ "iter-time=10",
71
"cipher-alg=%s-%d" % (config.cipher, config.keylen),
72
"cipher-mode=%s" % config.mode,
73
"ivgen-alg=%s" % config.ivgen,
74
diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out
75
index XXXXXXX..XXXXXXX 100644
76
--- a/tests/qemu-iotests/149.out
77
+++ b/tests/qemu-iotests/149.out
78
@@ -XXX,XX +XXX,XX @@
79
# Create image
80
truncate TEST_DIR/luks-aes-256-xts-plain64-sha1.img --size 4194304MB
81
# Format image
82
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha1.img
83
+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
84
# Open dev
85
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
86
# Set dev owner
87
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img
88
89
# ================= qemu-img aes-256-xts-plain64-sha1 =================
90
# Create image
91
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain64-sha1.img 4194304M
92
-Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
93
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain64-sha1.img 4194304M
94
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
95
96
# Open dev
97
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
98
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img
99
# Create image
100
truncate TEST_DIR/luks-twofish-256-xts-plain64-sha1.img --size 4194304MB
101
# Format image
102
-sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
103
+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
104
# Open dev
105
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
106
# Set dev owner
107
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
108
109
# ================= qemu-img twofish-256-xts-plain64-sha1 =================
110
# Create image
111
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img 4194304M
112
-Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
113
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=twofish-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img 4194304M
114
+Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
115
116
# Open dev
117
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
118
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
119
# Create image
120
truncate TEST_DIR/luks-serpent-256-xts-plain64-sha1.img --size 4194304MB
121
# Format image
122
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
123
+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
124
# Open dev
125
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
126
# Set dev owner
127
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
128
129
# ================= qemu-img serpent-256-xts-plain64-sha1 =================
130
# Create image
131
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img 4194304M
132
-Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
133
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img 4194304M
134
+Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
135
136
# Open dev
137
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
138
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
139
# Create image
140
truncate TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img --size 4194304MB
141
# Format image
142
-sudo cryptsetup -q -v luksFormat --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
143
+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
144
# Open dev
145
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
146
# Set dev owner
147
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
148
149
# ================= qemu-img cast5-128-cbc-plain64-sha1 =================
150
# Create image
151
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=cast5-128,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img 4194304M
152
-Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=cast5-128 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1
153
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=cast5-128,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img 4194304M
154
+Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=cast5-128 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 iter-time=10
155
156
# Open dev
157
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
158
@@ -XXX,XX +XXX,XX @@ Skipping cast6-256-xts-plain64-sha1 in blacklist
159
# Create image
160
truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB
161
# Format image
162
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain-sha1.img
163
+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
164
# Open dev
165
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
166
# Set dev owner
167
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img
168
169
# ================= qemu-img aes-256-cbc-plain-sha1 =================
170
# Create image
171
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain-sha1.img 4194304M
172
-Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain hash-alg=sha1
173
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain-sha1.img 4194304M
174
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain hash-alg=sha1 iter-time=10
175
176
# Open dev
177
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
178
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img
179
# Create image
180
truncate TEST_DIR/luks-aes-256-cbc-plain64-sha1.img --size 4194304MB
181
# Format image
182
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
183
+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
184
# Open dev
185
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
186
# Set dev owner
187
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
188
189
# ================= qemu-img aes-256-cbc-plain64-sha1 =================
190
# Create image
191
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img 4194304M
192
-Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1
193
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img 4194304M
194
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1 iter-time=10
195
196
# Open dev
197
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
198
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
199
# Create image
200
truncate TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img --size 4194304MB
201
# Format image
202
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
203
+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
204
# Open dev
205
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
206
# Set dev owner
207
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
208
209
# ================= qemu-img aes-256-cbc-essiv-sha256-sha1 =================
210
# Create image
211
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img 4194304M
212
-Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1
213
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img 4194304M
214
+Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10
215
216
# Open dev
217
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
218
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
219
# Create image
220
truncate TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img --size 4194304MB
221
# Format image
222
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
223
+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
224
# Open dev
225
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
226
# Set dev owner
227
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
228
229
# ================= qemu-img aes-256-xts-essiv-sha256-sha1 =================
230
# Create image
231
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img 4194304M
232
-Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1
233
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img 4194304M
234
+Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10
235
236
# Open dev
237
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
238
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
239
# Create image
240
truncate TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img --size 4194304MB
241
# Format image
242
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
243
+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
244
# Open dev
245
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
246
# Set dev owner
247
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
248
249
# ================= qemu-img aes-128-xts-plain64-sha256-sha1 =================
250
# Create image
251
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img 4194304M
252
-Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
253
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img 4194304M
254
+Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
255
256
# Open dev
257
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
258
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
259
# Create image
260
truncate TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img --size 4194304MB
261
# Format image
262
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
263
+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
264
# Open dev
265
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
266
# Set dev owner
267
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
268
269
# ================= qemu-img aes-192-xts-plain64-sha256-sha1 =================
270
# Create image
271
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img 4194304M
272
-Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
273
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img 4194304M
274
+Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
275
276
# Open dev
277
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
278
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
279
# Create image
280
truncate TEST_DIR/luks-twofish-128-xts-plain64-sha1.img --size 4194304MB
281
# Format image
282
-sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
283
+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
284
# Open dev
285
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
286
# Set dev owner
287
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
288
289
# ================= qemu-img twofish-128-xts-plain64-sha1 =================
290
# Create image
291
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img 4194304M
292
-Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
293
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=twofish-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img 4194304M
294
+Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
295
296
# Open dev
297
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
298
@@ -XXX,XX +XXX,XX @@ Skipping twofish-192-xts-plain64-sha1 in blacklist
299
# Create image
300
truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB
301
# Format image
302
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
303
+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
304
# Open dev
305
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
306
# Set dev owner
307
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
308
309
# ================= qemu-img serpent-128-xts-plain64-sha1 =================
310
# Create image
311
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img 4194304M
312
-Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
313
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img 4194304M
314
+Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
315
316
# Open dev
317
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
318
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
319
# Create image
320
truncate TEST_DIR/luks-serpent-192-xts-plain64-sha1.img --size 4194304MB
321
# Format image
322
-sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
323
+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
324
# Open dev
325
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
326
# Set dev owner
327
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
328
329
# ================= qemu-img serpent-192-xts-plain64-sha1 =================
330
# Create image
331
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img 4194304M
332
-Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
333
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=serpent-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img 4194304M
334
+Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1 iter-time=10
335
336
# Open dev
337
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
338
@@ -XXX,XX +XXX,XX @@ Skipping cast6-192-xts-plain64-sha1 in blacklist
339
# Create image
340
truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB
341
# Format image
342
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha256.img
343
+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
344
# Open dev
345
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
346
# Set dev owner
347
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img
348
349
# ================= qemu-img aes-256-xts-plain64-sha256 =================
350
# Create image
351
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha256 TEST_DIR/luks-aes-256-xts-plain64-sha256.img 4194304M
352
-Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha256
353
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha256 TEST_DIR/luks-aes-256-xts-plain64-sha256.img 4194304M
354
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha256 iter-time=10
355
356
# Open dev
357
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
358
@@ -XXX,XX +XXX,XX @@ Skipping aes-256-xts-plain64-ripemd160 in blacklist
359
# Create image
360
truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB
361
# Format image
362
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
363
+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
364
# Open dev
365
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
366
# Set dev owner
367
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
368
# Create image
369
truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --size 4194304MB
370
# Format image
371
-sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
372
+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
373
# Add password slot 1
374
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 1 --key-file - TEST_DIR/passwd.txt
375
+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
376
# Add password slot 2
377
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 2 --key-file - TEST_DIR/passwd.txt
378
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 2 --key-file - --iter-time 10 TEST_DIR/passwd.txt
379
# Add password slot 3
380
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 3 --key-file - TEST_DIR/passwd.txt
381
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 3 --key-file - --iter-time 10 TEST_DIR/passwd.txt
382
# Add password slot 4
383
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 4 --key-file - TEST_DIR/passwd.txt
384
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 4 --key-file - --iter-time 10 TEST_DIR/passwd.txt
385
# Add password slot 5
386
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 5 --key-file - TEST_DIR/passwd.txt
387
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 5 --key-file - --iter-time 10 TEST_DIR/passwd.txt
388
# Add password slot 6
389
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 6 --key-file - TEST_DIR/passwd.txt
390
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 6 --key-file - --iter-time 10 TEST_DIR/passwd.txt
391
# Add password slot 7
392
-sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - TEST_DIR/passwd.txt
393
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - --iter-time 10 TEST_DIR/passwd.txt
394
# Open dev
395
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
396
# Set dev owner
397
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
398
399
# ================= qemu-img aes-256-xts-plain-sha1-pwallslots =================
400
# Create image
401
-qemu-img create -f luks --object secret,id=sec0,data=c2xvdDE=,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img 4194304M
402
-Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain hash-alg=sha1
403
+qemu-img create -f luks --object secret,id=sec0,data=c2xvdDE=,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img 4194304M
404
+Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain hash-alg=sha1 iter-time=10
405
406
# Open dev
407
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
408
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
409
# Create image
410
truncate TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img --size 4194304MB
411
# Format image
412
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
413
+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
414
# Open dev
415
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
416
# Set dev owner
417
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
418
419
# ================= qemu-img aes-256-cbc-essiv-auto-sha1 =================
420
# Create image
421
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img 4194304M
422
-Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv hash-alg=sha1
423
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img 4194304M
424
+Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv hash-alg=sha1 iter-time=10
425
426
# Open dev
427
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
428
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img
429
# Create image
430
truncate TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img --size 4194304MB
431
# Format image
432
-sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
433
+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
434
# Open dev
435
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
436
# Set dev owner
437
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img
438
439
# ================= qemu-img aes-256-cbc-plain64-sha256-sha1 =================
440
# Create image
441
-qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img 4194304M
442
-Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 ivgen-hash-alg=sha256 hash-alg=sha1
443
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img 4194304M
444
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 ivgen-hash-alg=sha256 hash-alg=sha1 iter-time=10
445
446
# Open dev
447
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
448
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
449
index XXXXXXX..XXXXXXX 100644
450
--- a/tests/qemu-iotests/common.filter
451
+++ b/tests/qemu-iotests/common.filter
452
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
453
-e "s# block_state_zero=\\(on\\|off\\)##g" \
454
-e "s# log_size=[0-9]\\+##g" \
455
-e "s# refcount_bits=[0-9]\\+##g" \
456
- -e "s# key-secret=[a-zA-Z0-9]\\+##g"
457
+ -e "s# key-secret=[a-zA-Z0-9]\\+##g" \
458
+ -e "s# iter-time=[0-9]\\+##g"
459
}
460
461
_filter_img_info()
462
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
463
index XXXXXXX..XXXXXXX 100644
464
--- a/tests/qemu-iotests/common.rc
465
+++ b/tests/qemu-iotests/common.rc
466
@@ -XXX,XX +XXX,XX @@ _set_default_imgopts()
467
if [ "$IMGFMT" == "qcow2" ] && ! (echo "$IMGOPTS" | grep "compat=" > /dev/null); then
468
IMGOPTS=$(_optstr_add "$IMGOPTS" "compat=1.1")
469
fi
470
+ if [ "$IMGFMT" == "luks" ] && ! (echo "$IMGOPTS" | grep "iter-time=" > /dev/null); then
471
+ IMGOPTS=$(_optstr_add "$IMGOPTS" "iter-time=10")
472
+ fi
473
}
474
475
_use_sample_img()
476
--
477
1.8.3.1
478
479
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
Add tests for sha224, sha512, sha384 and ripemd160 hash
4
algorithms.
5
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
9
Message-id: 20170626123510.20134-5-berrange@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/149 | 10 +-
13
tests/qemu-iotests/149.out | 482 ++++++++++++++++++++++++++++++++++++++++++++-
14
2 files changed, 484 insertions(+), 8 deletions(-)
15
16
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/149
19
+++ b/tests/qemu-iotests/149
20
@@ -XXX,XX +XXX,XX @@ configs = [
21
22
23
# LUKS default but diff hash
24
+ LUKSConfig("aes-256-xts-plain64-sha224",
25
+ "aes", 256, "xts", "plain64", None, "sha224"),
26
LUKSConfig("aes-256-xts-plain64-sha256",
27
"aes", 256, "xts", "plain64", None, "sha256"),
28
+ LUKSConfig("aes-256-xts-plain64-sha384",
29
+ "aes", 256, "xts", "plain64", None, "sha384"),
30
LUKSConfig("aes-256-xts-plain64-sha512",
31
"aes", 256, "xts", "plain64", None, "sha512"),
32
LUKSConfig("aes-256-xts-plain64-ripemd160",
33
@@ -XXX,XX +XXX,XX @@ blacklist = [
34
35
# GCrypt doesn't support Twofish with 192 bit key
36
"twofish-192-xts-plain64-sha1",
37
-
38
- # We don't have sha512 hash wired up yet
39
- "aes-256-xts-plain64-sha512",
40
-
41
- # We don't have ripemd160 hash wired up yet
42
- "aes-256-xts-plain64-ripemd160",
43
]
44
45
whitelist = []
46
diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out
47
index XXXXXXX..XXXXXXX 100644
48
--- a/tests/qemu-iotests/149.out
49
+++ b/tests/qemu-iotests/149.out
50
@@ -XXX,XX +XXX,XX @@ unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
51
52
Skipping cast6-128-xts-plain64-sha1 in blacklist
53
Skipping cast6-192-xts-plain64-sha1 in blacklist
54
+# ================= dm-crypt aes-256-xts-plain64-sha224 =================
55
+# Create image
56
+truncate TEST_DIR/luks-aes-256-xts-plain64-sha224.img --size 4194304MB
57
+# Format image
58
+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
59
+# Open dev
60
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
61
+# Set dev owner
62
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
63
+# Write test pattern 0xa7
64
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
65
+wrote 10485760/10485760 bytes at offset 104857600
66
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
+
68
+# Write test pattern 0x13
69
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
70
+wrote 10485760/10485760 bytes at offset 3298534883328
71
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
72
+
73
+# Close dev
74
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224
75
+# Read test pattern 0xa7
76
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
77
+read 10485760/10485760 bytes at offset 104857600
78
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
79
+
80
+# Read test pattern 0x13
81
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
82
+read 10485760/10485760 bytes at offset 3298534883328
83
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
84
+
85
+# Write test pattern 0x91
86
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
87
+wrote 10485760/10485760 bytes at offset 104857600
88
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
89
+
90
+# Write test pattern 0x5e
91
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
92
+wrote 10485760/10485760 bytes at offset 3298534883328
93
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
94
+
95
+# Open dev
96
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
97
+# Set dev owner
98
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
99
+# Read test pattern 0x91
100
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
101
+read 10485760/10485760 bytes at offset 104857600
102
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
103
+
104
+# Read test pattern 0x5e
105
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
106
+read 10485760/10485760 bytes at offset 3298534883328
107
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
108
+
109
+# Close dev
110
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224
111
+# Delete image
112
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha224.img
113
+
114
+# ================= qemu-img aes-256-xts-plain64-sha224 =================
115
+# Create image
116
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha224 TEST_DIR/luks-aes-256-xts-plain64-sha224.img 4194304M
117
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha224.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha224 iter-time=10
118
+
119
+# Open dev
120
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
121
+# Set dev owner
122
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
123
+# Write test pattern 0xa7
124
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
125
+wrote 10485760/10485760 bytes at offset 104857600
126
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
127
+
128
+# Write test pattern 0x13
129
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
130
+wrote 10485760/10485760 bytes at offset 3298534883328
131
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
132
+
133
+# Close dev
134
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224
135
+# Read test pattern 0xa7
136
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
137
+read 10485760/10485760 bytes at offset 104857600
138
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
139
+
140
+# Read test pattern 0x13
141
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
142
+read 10485760/10485760 bytes at offset 3298534883328
143
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
144
+
145
+# Write test pattern 0x91
146
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
147
+wrote 10485760/10485760 bytes at offset 104857600
148
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
149
+
150
+# Write test pattern 0x5e
151
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha224.img
152
+wrote 10485760/10485760 bytes at offset 3298534883328
153
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
154
+
155
+# Open dev
156
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
157
+# Set dev owner
158
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
159
+# Read test pattern 0x91
160
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
161
+read 10485760/10485760 bytes at offset 104857600
162
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
163
+
164
+# Read test pattern 0x5e
165
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
166
+read 10485760/10485760 bytes at offset 3298534883328
167
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
+
169
+# Close dev
170
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha224
171
+# Delete image
172
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha224.img
173
+
174
# ================= dm-crypt aes-256-xts-plain64-sha256 =================
175
# Create image
176
truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB
177
@@ -XXX,XX +XXX,XX @@ sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256
178
# Delete image
179
unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img
180
181
-Skipping aes-256-xts-plain64-sha512 in blacklist
182
-Skipping aes-256-xts-plain64-ripemd160 in blacklist
183
+# ================= dm-crypt aes-256-xts-plain64-sha384 =================
184
+# Create image
185
+truncate TEST_DIR/luks-aes-256-xts-plain64-sha384.img --size 4194304MB
186
+# Format image
187
+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
188
+# Open dev
189
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
190
+# Set dev owner
191
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
192
+# Write test pattern 0xa7
193
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
194
+wrote 10485760/10485760 bytes at offset 104857600
195
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
196
+
197
+# Write test pattern 0x13
198
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
199
+wrote 10485760/10485760 bytes at offset 3298534883328
200
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
201
+
202
+# Close dev
203
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384
204
+# Read test pattern 0xa7
205
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
206
+read 10485760/10485760 bytes at offset 104857600
207
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
208
+
209
+# Read test pattern 0x13
210
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
211
+read 10485760/10485760 bytes at offset 3298534883328
212
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
213
+
214
+# Write test pattern 0x91
215
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
216
+wrote 10485760/10485760 bytes at offset 104857600
217
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
218
+
219
+# Write test pattern 0x5e
220
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
221
+wrote 10485760/10485760 bytes at offset 3298534883328
222
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
223
+
224
+# Open dev
225
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
226
+# Set dev owner
227
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
228
+# Read test pattern 0x91
229
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
230
+read 10485760/10485760 bytes at offset 104857600
231
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
232
+
233
+# Read test pattern 0x5e
234
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
235
+read 10485760/10485760 bytes at offset 3298534883328
236
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
237
+
238
+# Close dev
239
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384
240
+# Delete image
241
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha384.img
242
+
243
+# ================= qemu-img aes-256-xts-plain64-sha384 =================
244
+# Create image
245
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha384 TEST_DIR/luks-aes-256-xts-plain64-sha384.img 4194304M
246
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha384.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha384 iter-time=10
247
+
248
+# Open dev
249
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
250
+# Set dev owner
251
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
252
+# Write test pattern 0xa7
253
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
254
+wrote 10485760/10485760 bytes at offset 104857600
255
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
256
+
257
+# Write test pattern 0x13
258
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
259
+wrote 10485760/10485760 bytes at offset 3298534883328
260
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
261
+
262
+# Close dev
263
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384
264
+# Read test pattern 0xa7
265
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
266
+read 10485760/10485760 bytes at offset 104857600
267
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
268
+
269
+# Read test pattern 0x13
270
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
271
+read 10485760/10485760 bytes at offset 3298534883328
272
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+# Write test pattern 0x91
275
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
276
+wrote 10485760/10485760 bytes at offset 104857600
277
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
278
+
279
+# Write test pattern 0x5e
280
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha384.img
281
+wrote 10485760/10485760 bytes at offset 3298534883328
282
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+# Open dev
285
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
286
+# Set dev owner
287
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
288
+# Read test pattern 0x91
289
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
290
+read 10485760/10485760 bytes at offset 104857600
291
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
292
+
293
+# Read test pattern 0x5e
294
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
295
+read 10485760/10485760 bytes at offset 3298534883328
296
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
297
+
298
+# Close dev
299
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha384
300
+# Delete image
301
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha384.img
302
+
303
+# ================= dm-crypt aes-256-xts-plain64-sha512 =================
304
+# Create image
305
+truncate TEST_DIR/luks-aes-256-xts-plain64-sha512.img --size 4194304MB
306
+# Format image
307
+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
308
+# Open dev
309
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
310
+# Set dev owner
311
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
312
+# Write test pattern 0xa7
313
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
314
+wrote 10485760/10485760 bytes at offset 104857600
315
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
316
+
317
+# Write test pattern 0x13
318
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
319
+wrote 10485760/10485760 bytes at offset 3298534883328
320
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
321
+
322
+# Close dev
323
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512
324
+# Read test pattern 0xa7
325
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
326
+read 10485760/10485760 bytes at offset 104857600
327
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
328
+
329
+# Read test pattern 0x13
330
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
331
+read 10485760/10485760 bytes at offset 3298534883328
332
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
333
+
334
+# Write test pattern 0x91
335
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
336
+wrote 10485760/10485760 bytes at offset 104857600
337
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
338
+
339
+# Write test pattern 0x5e
340
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
341
+wrote 10485760/10485760 bytes at offset 3298534883328
342
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
343
+
344
+# Open dev
345
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
346
+# Set dev owner
347
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
348
+# Read test pattern 0x91
349
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
350
+read 10485760/10485760 bytes at offset 104857600
351
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
352
+
353
+# Read test pattern 0x5e
354
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
355
+read 10485760/10485760 bytes at offset 3298534883328
356
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
357
+
358
+# Close dev
359
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512
360
+# Delete image
361
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha512.img
362
+
363
+# ================= qemu-img aes-256-xts-plain64-sha512 =================
364
+# Create image
365
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha512 TEST_DIR/luks-aes-256-xts-plain64-sha512.img 4194304M
366
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha512.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha512 iter-time=10
367
+
368
+# Open dev
369
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
370
+# Set dev owner
371
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
372
+# Write test pattern 0xa7
373
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
374
+wrote 10485760/10485760 bytes at offset 104857600
375
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
376
+
377
+# Write test pattern 0x13
378
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
379
+wrote 10485760/10485760 bytes at offset 3298534883328
380
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
381
+
382
+# Close dev
383
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512
384
+# Read test pattern 0xa7
385
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
386
+read 10485760/10485760 bytes at offset 104857600
387
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
388
+
389
+# Read test pattern 0x13
390
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
391
+read 10485760/10485760 bytes at offset 3298534883328
392
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
393
+
394
+# Write test pattern 0x91
395
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
396
+wrote 10485760/10485760 bytes at offset 104857600
397
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+# Write test pattern 0x5e
400
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha512.img
401
+wrote 10485760/10485760 bytes at offset 3298534883328
402
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+# Open dev
405
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
406
+# Set dev owner
407
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
408
+# Read test pattern 0x91
409
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
410
+read 10485760/10485760 bytes at offset 104857600
411
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
412
+
413
+# Read test pattern 0x5e
414
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
415
+read 10485760/10485760 bytes at offset 3298534883328
416
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
417
+
418
+# Close dev
419
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha512
420
+# Delete image
421
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha512.img
422
+
423
+# ================= dm-crypt aes-256-xts-plain64-ripemd160 =================
424
+# Create image
425
+truncate TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img --size 4194304MB
426
+# Format image
427
+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
428
+# Open dev
429
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
430
+# Set dev owner
431
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
432
+# Write test pattern 0xa7
433
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
434
+wrote 10485760/10485760 bytes at offset 104857600
435
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
436
+
437
+# Write test pattern 0x13
438
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
439
+wrote 10485760/10485760 bytes at offset 3298534883328
440
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
441
+
442
+# Close dev
443
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160
444
+# Read test pattern 0xa7
445
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
446
+read 10485760/10485760 bytes at offset 104857600
447
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
448
+
449
+# Read test pattern 0x13
450
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
451
+read 10485760/10485760 bytes at offset 3298534883328
452
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
453
+
454
+# Write test pattern 0x91
455
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
456
+wrote 10485760/10485760 bytes at offset 104857600
457
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
458
+
459
+# Write test pattern 0x5e
460
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
461
+wrote 10485760/10485760 bytes at offset 3298534883328
462
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
463
+
464
+# Open dev
465
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
466
+# Set dev owner
467
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
468
+# Read test pattern 0x91
469
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
470
+read 10485760/10485760 bytes at offset 104857600
471
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
472
+
473
+# Read test pattern 0x5e
474
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
475
+read 10485760/10485760 bytes at offset 3298534883328
476
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
477
+
478
+# Close dev
479
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160
480
+# Delete image
481
+unlink TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
482
+
483
+# ================= qemu-img aes-256-xts-plain64-ripemd160 =================
484
+# Create image
485
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,iter-time=10,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=ripemd160 TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img 4194304M
486
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=ripemd160 iter-time=10
487
+
488
+# Open dev
489
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
490
+# Set dev owner
491
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
492
+# Write test pattern 0xa7
493
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
494
+wrote 10485760/10485760 bytes at offset 104857600
495
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
496
+
497
+# Write test pattern 0x13
498
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
499
+wrote 10485760/10485760 bytes at offset 3298534883328
500
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
501
+
502
+# Close dev
503
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160
504
+# Read test pattern 0xa7
505
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
506
+read 10485760/10485760 bytes at offset 104857600
507
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
508
+
509
+# Read test pattern 0x13
510
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
511
+read 10485760/10485760 bytes at offset 3298534883328
512
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
513
+
514
+# Write test pattern 0x91
515
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
516
+wrote 10485760/10485760 bytes at offset 104857600
517
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
518
+
519
+# Write test pattern 0x5e
520
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
521
+wrote 10485760/10485760 bytes at offset 3298534883328
522
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
523
+
524
+# Open dev
525
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
526
+# Set dev owner
527
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
528
+# Read test pattern 0x91
529
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
530
+read 10485760/10485760 bytes at offset 104857600
531
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
532
+
533
+# Read test pattern 0x5e
534
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
535
+read 10485760/10485760 bytes at offset 3298534883328
536
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
537
+
538
+# Close dev
539
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-ripemd160
540
+# Delete image
541
+unlink TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img
542
+
543
# ================= dm-crypt aes-256-xts-plain-sha1-pwslot3 =================
544
# Create image
545
truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB
546
--
547
1.8.3.1
548
549
diff view generated by jsdifflib
Deleted patch
1
From: "Daniel P. Berrange" <berrange@redhat.com>
2
1
3
On some distros, whenever you close a block device file
4
descriptor there is a udev rule that resets the file
5
permissions. This can race with the test script when
6
we run qemu-io multiple times against the same block
7
device. Occasionally the second qemu-io invocation
8
will find udev has reset the permissions causing failure.
9
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
13
Message-id: 20170626123510.20134-6-berrange@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
tests/qemu-iotests/149 | 12 +-
17
tests/qemu-iotests/149.out | 344 ++++++++++++++++++++++-----------------------
18
2 files changed, 177 insertions(+), 179 deletions(-)
19
20
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/149
23
+++ b/tests/qemu-iotests/149
24
@@ -XXX,XX +XXX,XX @@ def chown(config):
25
msg = proc.communicate()[0]
26
27
if proc.returncode != 0:
28
- raise Exception("Cannot change owner on %s" % path)
29
+ raise Exception(msg)
30
31
32
def cryptsetup_open(config):
33
@@ -XXX,XX +XXX,XX @@ def qemu_io_image_args(config, dev=False):
34
def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
35
"""Write a pattern of data to a LUKS image or device"""
36
37
+ if dev:
38
+ chown(config)
39
args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
40
args.extend(qemu_io_image_args(config, dev))
41
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
42
@@ -XXX,XX +XXX,XX @@ def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
43
def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
44
"""Read a pattern of data to a LUKS image or device"""
45
46
+ if dev:
47
+ chown(config)
48
args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
49
args.extend(qemu_io_image_args(config, dev))
50
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
51
@@ -XXX,XX +XXX,XX @@ def test_once(config, qemu_img=False):
52
cryptsetup_open(config)
53
54
try:
55
- iotests.log("# Set dev owner")
56
- chown(config)
57
-
58
iotests.log("# Write test pattern 0xa7")
59
qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True)
60
iotests.log("# Write test pattern 0x13")
61
@@ -XXX,XX +XXX,XX @@ def test_once(config, qemu_img=False):
62
cryptsetup_open(config)
63
64
try:
65
- iotests.log("# Set dev owner")
66
- chown(config)
67
-
68
iotests.log("# Read test pattern 0x91")
69
qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True)
70
iotests.log("# Read test pattern 0x5e")
71
diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out
72
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/149.out
74
+++ b/tests/qemu-iotests/149.out
75
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-sha1.img --size 4194304MB
76
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
77
# Open dev
78
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
79
-# Set dev owner
80
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
81
# Write test pattern 0xa7
82
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
83
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
84
wrote 10485760/10485760 bytes at offset 104857600
85
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
87
# Write test pattern 0x13
88
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
89
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
90
wrote 10485760/10485760 bytes at offset 3298534883328
91
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
92
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
93
94
# Open dev
95
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
96
-# Set dev owner
97
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
98
# Read test pattern 0x91
99
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
100
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
101
read 10485760/10485760 bytes at offset 104857600
102
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
103
104
# Read test pattern 0x5e
105
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
106
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
107
read 10485760/10485760 bytes at offset 3298534883328
108
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=439804651
110
111
# Open dev
112
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
113
-# Set dev owner
114
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
115
# Write test pattern 0xa7
116
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
117
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
118
wrote 10485760/10485760 bytes at offset 104857600
119
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
120
121
# Write test pattern 0x13
122
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
123
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
124
wrote 10485760/10485760 bytes at offset 3298534883328
125
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
126
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
127
128
# Open dev
129
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
130
-# Set dev owner
131
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
132
# Read test pattern 0x91
133
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
134
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
135
read 10485760/10485760 bytes at offset 104857600
136
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
137
138
# Read test pattern 0x5e
139
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
140
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
141
read 10485760/10485760 bytes at offset 3298534883328
142
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
143
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-twofish-256-xts-plain64-sha1.img --size 4194304MB
144
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
145
# Open dev
146
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
147
-# Set dev owner
148
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
149
# Write test pattern 0xa7
150
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
151
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
152
wrote 10485760/10485760 bytes at offset 104857600
153
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
154
155
# Write test pattern 0x13
156
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
157
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
158
wrote 10485760/10485760 bytes at offset 3298534883328
159
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
160
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
161
162
# Open dev
163
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
164
-# Set dev owner
165
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
166
# Read test pattern 0x91
167
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
168
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
169
read 10485760/10485760 bytes at offset 104857600
170
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
171
172
# Read test pattern 0x5e
173
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
174
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
175
read 10485760/10485760 bytes at offset 3298534883328
176
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
177
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=43980
178
179
# Open dev
180
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
181
-# Set dev owner
182
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
183
# Write test pattern 0xa7
184
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
185
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
186
wrote 10485760/10485760 bytes at offset 104857600
187
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
188
189
# Write test pattern 0x13
190
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
191
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
192
wrote 10485760/10485760 bytes at offset 3298534883328
193
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
195
196
# Open dev
197
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
198
-# Set dev owner
199
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
200
# Read test pattern 0x91
201
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
202
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
203
read 10485760/10485760 bytes at offset 104857600
204
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
205
206
# Read test pattern 0x5e
207
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
208
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
209
read 10485760/10485760 bytes at offset 3298534883328
210
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
211
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-serpent-256-xts-plain64-sha1.img --size 4194304MB
212
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
213
# Open dev
214
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
215
-# Set dev owner
216
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
217
# Write test pattern 0xa7
218
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
219
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
220
wrote 10485760/10485760 bytes at offset 104857600
221
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
222
223
# Write test pattern 0x13
224
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
225
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
226
wrote 10485760/10485760 bytes at offset 3298534883328
227
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
228
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
229
230
# Open dev
231
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
232
-# Set dev owner
233
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
234
# Read test pattern 0x91
235
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
236
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
237
read 10485760/10485760 bytes at offset 104857600
238
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
239
240
# Read test pattern 0x5e
241
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
242
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
243
read 10485760/10485760 bytes at offset 3298534883328
244
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
245
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=43980
246
247
# Open dev
248
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
249
-# Set dev owner
250
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
251
# Write test pattern 0xa7
252
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
253
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
254
wrote 10485760/10485760 bytes at offset 104857600
255
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
256
257
# Write test pattern 0x13
258
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
259
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
260
wrote 10485760/10485760 bytes at offset 3298534883328
261
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
262
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
263
264
# Open dev
265
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
266
-# Set dev owner
267
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
268
# Read test pattern 0x91
269
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
270
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
271
read 10485760/10485760 bytes at offset 104857600
272
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
274
# Read test pattern 0x5e
275
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
276
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
277
read 10485760/10485760 bytes at offset 3298534883328
278
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
279
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img --size 4194304MB
280
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
281
# Open dev
282
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
283
-# Set dev owner
284
-sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
285
# Write test pattern 0xa7
286
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
287
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
288
wrote 10485760/10485760 bytes at offset 104857600
289
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
290
291
# Write test pattern 0x13
292
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
293
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
294
wrote 10485760/10485760 bytes at offset 3298534883328
295
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
296
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
297
298
# Open dev
299
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
300
-# Set dev owner
301
-sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
302
# Read test pattern 0x91
303
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
304
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
305
read 10485760/10485760 bytes at offset 104857600
306
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
307
308
# Read test pattern 0x5e
309
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
310
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
311
read 10485760/10485760 bytes at offset 3298534883328
312
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
313
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046
314
315
# Open dev
316
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
317
-# Set dev owner
318
-sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
319
# Write test pattern 0xa7
320
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
321
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
322
wrote 10485760/10485760 bytes at offset 104857600
323
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
324
325
# Write test pattern 0x13
326
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
327
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
328
wrote 10485760/10485760 bytes at offset 3298534883328
329
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
330
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
331
332
# Open dev
333
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
334
-# Set dev owner
335
-sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
336
# Read test pattern 0x91
337
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
338
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
339
read 10485760/10485760 bytes at offset 104857600
340
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
342
# Read test pattern 0x5e
343
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
344
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
345
read 10485760/10485760 bytes at offset 3298534883328
346
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
347
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB
348
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
349
# Open dev
350
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
351
-# Set dev owner
352
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
353
# Write test pattern 0xa7
354
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
355
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
356
wrote 10485760/10485760 bytes at offset 104857600
357
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
358
359
# Write test pattern 0x13
360
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
361
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
362
wrote 10485760/10485760 bytes at offset 3298534883328
363
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
364
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
365
366
# Open dev
367
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
368
-# Set dev owner
369
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
370
# Read test pattern 0x91
371
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
372
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
373
read 10485760/10485760 bytes at offset 104857600
374
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
375
376
# Read test pattern 0x5e
377
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
378
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
379
read 10485760/10485760 bytes at offset 3298534883328
380
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
381
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=43980465111
382
383
# Open dev
384
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
385
-# Set dev owner
386
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
387
# Write test pattern 0xa7
388
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
389
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
390
wrote 10485760/10485760 bytes at offset 104857600
391
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
392
393
# Write test pattern 0x13
394
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
395
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
396
wrote 10485760/10485760 bytes at offset 3298534883328
397
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
399
400
# Open dev
401
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
402
-# Set dev owner
403
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
404
# Read test pattern 0x91
405
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
406
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
407
read 10485760/10485760 bytes at offset 104857600
408
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
409
410
# Read test pattern 0x5e
411
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
412
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
413
read 10485760/10485760 bytes at offset 3298534883328
414
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
415
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-cbc-plain64-sha1.img --size 4194304MB
416
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
417
# Open dev
418
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
419
-# Set dev owner
420
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
421
# Write test pattern 0xa7
422
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
423
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
424
wrote 10485760/10485760 bytes at offset 104857600
425
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
426
427
# Write test pattern 0x13
428
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
429
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
430
wrote 10485760/10485760 bytes at offset 3298534883328
431
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
432
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
433
434
# Open dev
435
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
436
-# Set dev owner
437
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
438
# Read test pattern 0x91
439
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
440
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
441
read 10485760/10485760 bytes at offset 104857600
442
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
443
444
# Read test pattern 0x5e
445
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
446
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
447
read 10485760/10485760 bytes at offset 3298534883328
448
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
449
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=439804651
450
451
# Open dev
452
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
453
-# Set dev owner
454
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
455
# Write test pattern 0xa7
456
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
457
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
458
wrote 10485760/10485760 bytes at offset 104857600
459
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
460
461
# Write test pattern 0x13
462
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
463
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
464
wrote 10485760/10485760 bytes at offset 3298534883328
465
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
466
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
467
468
# Open dev
469
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
470
-# Set dev owner
471
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
472
# Read test pattern 0x91
473
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
474
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
475
read 10485760/10485760 bytes at offset 104857600
476
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
477
478
# Read test pattern 0x5e
479
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
480
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
481
read 10485760/10485760 bytes at offset 3298534883328
482
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
483
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img --size 4194304MB
484
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
485
# Open dev
486
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
487
-# Set dev owner
488
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
489
# Write test pattern 0xa7
490
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
491
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
492
wrote 10485760/10485760 bytes at offset 104857600
493
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
494
495
# Write test pattern 0x13
496
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
497
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
498
wrote 10485760/10485760 bytes at offset 3298534883328
499
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
500
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
501
502
# Open dev
503
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
504
-# Set dev owner
505
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
506
# Read test pattern 0x91
507
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
508
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
509
read 10485760/10485760 bytes at offset 104857600
510
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
511
512
# Read test pattern 0x5e
513
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
514
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
515
read 10485760/10485760 bytes at offset 3298534883328
516
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
517
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398
518
519
# Open dev
520
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
521
-# Set dev owner
522
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
523
# Write test pattern 0xa7
524
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
525
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
526
wrote 10485760/10485760 bytes at offset 104857600
527
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
528
529
# Write test pattern 0x13
530
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
531
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
532
wrote 10485760/10485760 bytes at offset 3298534883328
533
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
534
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
535
536
# Open dev
537
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
538
-# Set dev owner
539
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
540
# Read test pattern 0x91
541
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
542
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
543
read 10485760/10485760 bytes at offset 104857600
544
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
545
546
# Read test pattern 0x5e
547
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
548
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
549
read 10485760/10485760 bytes at offset 3298534883328
550
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
551
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img --size 4194304MB
552
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
553
# Open dev
554
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
555
-# Set dev owner
556
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
557
# Write test pattern 0xa7
558
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
559
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
560
wrote 10485760/10485760 bytes at offset 104857600
561
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
562
563
# Write test pattern 0x13
564
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
565
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
566
wrote 10485760/10485760 bytes at offset 3298534883328
567
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
568
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
569
570
# Open dev
571
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
572
-# Set dev owner
573
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
574
# Read test pattern 0x91
575
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
576
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
577
read 10485760/10485760 bytes at offset 104857600
578
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
579
580
# Read test pattern 0x5e
581
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
582
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
583
read 10485760/10485760 bytes at offset 3298534883328
584
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
585
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398
586
587
# Open dev
588
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
589
-# Set dev owner
590
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
591
# Write test pattern 0xa7
592
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
593
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
594
wrote 10485760/10485760 bytes at offset 104857600
595
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
596
597
# Write test pattern 0x13
598
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
599
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
600
wrote 10485760/10485760 bytes at offset 3298534883328
601
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
602
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
603
604
# Open dev
605
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
606
-# Set dev owner
607
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
608
# Read test pattern 0x91
609
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
610
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
611
read 10485760/10485760 bytes at offset 104857600
612
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
613
614
# Read test pattern 0x5e
615
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
616
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
617
read 10485760/10485760 bytes at offset 3298534883328
618
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
619
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img --size 4194304MB
620
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
621
# Open dev
622
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
623
-# Set dev owner
624
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
625
# Write test pattern 0xa7
626
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
627
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
628
wrote 10485760/10485760 bytes at offset 104857600
629
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
630
631
# Write test pattern 0x13
632
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
633
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
634
wrote 10485760/10485760 bytes at offset 3298534883328
635
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
636
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
637
638
# Open dev
639
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
640
-# Set dev owner
641
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
642
# Read test pattern 0x91
643
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
644
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
645
read 10485760/10485760 bytes at offset 104857600
646
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
647
648
# Read test pattern 0x5e
649
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
650
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
651
read 10485760/10485760 bytes at offset 3298534883328
652
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
653
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=43
654
655
# Open dev
656
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
657
-# Set dev owner
658
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
659
# Write test pattern 0xa7
660
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
661
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
662
wrote 10485760/10485760 bytes at offset 104857600
663
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
664
665
# Write test pattern 0x13
666
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
667
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
668
wrote 10485760/10485760 bytes at offset 3298534883328
669
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
670
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
671
672
# Open dev
673
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
674
-# Set dev owner
675
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
676
# Read test pattern 0x91
677
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
678
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
679
read 10485760/10485760 bytes at offset 104857600
680
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
681
682
# Read test pattern 0x5e
683
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
684
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
685
read 10485760/10485760 bytes at offset 3298534883328
686
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
687
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img --size 4194304MB
688
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
689
# Open dev
690
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
691
-# Set dev owner
692
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
693
# Write test pattern 0xa7
694
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
695
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
696
wrote 10485760/10485760 bytes at offset 104857600
697
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
698
699
# Write test pattern 0x13
700
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
701
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
702
wrote 10485760/10485760 bytes at offset 3298534883328
703
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
704
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
705
706
# Open dev
707
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
708
-# Set dev owner
709
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
710
# Read test pattern 0x91
711
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
712
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
713
read 10485760/10485760 bytes at offset 104857600
714
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
715
716
# Read test pattern 0x5e
717
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
718
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
719
read 10485760/10485760 bytes at offset 3298534883328
720
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
721
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=43
722
723
# Open dev
724
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
725
-# Set dev owner
726
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
727
# Write test pattern 0xa7
728
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
729
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
730
wrote 10485760/10485760 bytes at offset 104857600
731
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
732
733
# Write test pattern 0x13
734
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
735
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
736
wrote 10485760/10485760 bytes at offset 3298534883328
737
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
738
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
739
740
# Open dev
741
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
742
-# Set dev owner
743
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
744
# Read test pattern 0x91
745
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
746
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
747
read 10485760/10485760 bytes at offset 104857600
748
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
749
750
# Read test pattern 0x5e
751
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
752
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
753
read 10485760/10485760 bytes at offset 3298534883328
754
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
755
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-twofish-128-xts-plain64-sha1.img --size 4194304MB
756
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
757
# Open dev
758
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
759
-# Set dev owner
760
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
761
# Write test pattern 0xa7
762
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
763
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
764
wrote 10485760/10485760 bytes at offset 104857600
765
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
766
767
# Write test pattern 0x13
768
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
769
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
770
wrote 10485760/10485760 bytes at offset 3298534883328
771
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
772
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
773
774
# Open dev
775
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
776
-# Set dev owner
777
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
778
# Read test pattern 0x91
779
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
780
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
781
read 10485760/10485760 bytes at offset 104857600
782
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
783
784
# Read test pattern 0x5e
785
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
786
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
787
read 10485760/10485760 bytes at offset 3298534883328
788
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
789
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=43980
790
791
# Open dev
792
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
793
-# Set dev owner
794
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
795
# Write test pattern 0xa7
796
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
797
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
798
wrote 10485760/10485760 bytes at offset 104857600
799
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
800
801
# Write test pattern 0x13
802
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
803
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
804
wrote 10485760/10485760 bytes at offset 3298534883328
805
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
806
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
807
808
# Open dev
809
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
810
-# Set dev owner
811
-sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
812
# Read test pattern 0x91
813
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
814
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
815
read 10485760/10485760 bytes at offset 104857600
816
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
817
818
# Read test pattern 0x5e
819
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
820
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
821
read 10485760/10485760 bytes at offset 3298534883328
822
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
823
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB
824
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
825
# Open dev
826
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
827
-# Set dev owner
828
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
829
# Write test pattern 0xa7
830
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
831
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
832
wrote 10485760/10485760 bytes at offset 104857600
833
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
834
835
# Write test pattern 0x13
836
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
837
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
838
wrote 10485760/10485760 bytes at offset 3298534883328
839
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
840
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
841
842
# Open dev
843
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
844
-# Set dev owner
845
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
846
# Read test pattern 0x91
847
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
848
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
849
read 10485760/10485760 bytes at offset 104857600
850
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
851
852
# Read test pattern 0x5e
853
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
854
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
855
read 10485760/10485760 bytes at offset 3298534883328
856
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
857
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=43980
858
859
# Open dev
860
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
861
-# Set dev owner
862
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
863
# Write test pattern 0xa7
864
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
865
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
866
wrote 10485760/10485760 bytes at offset 104857600
867
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
868
869
# Write test pattern 0x13
870
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
871
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
872
wrote 10485760/10485760 bytes at offset 3298534883328
873
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
874
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
875
876
# Open dev
877
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
878
-# Set dev owner
879
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
880
# Read test pattern 0x91
881
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
882
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
883
read 10485760/10485760 bytes at offset 104857600
884
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
885
886
# Read test pattern 0x5e
887
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
888
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
889
read 10485760/10485760 bytes at offset 3298534883328
890
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
891
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-serpent-192-xts-plain64-sha1.img --size 4194304MB
892
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
893
# Open dev
894
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
895
-# Set dev owner
896
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
897
# Write test pattern 0xa7
898
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
899
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
900
wrote 10485760/10485760 bytes at offset 104857600
901
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
902
903
# Write test pattern 0x13
904
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
905
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
906
wrote 10485760/10485760 bytes at offset 3298534883328
907
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
908
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
909
910
# Open dev
911
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
912
-# Set dev owner
913
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
914
# Read test pattern 0x91
915
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
916
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
917
read 10485760/10485760 bytes at offset 104857600
918
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
919
920
# Read test pattern 0x5e
921
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
922
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
923
read 10485760/10485760 bytes at offset 3298534883328
924
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
925
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=43980
926
927
# Open dev
928
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
929
-# Set dev owner
930
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
931
# Write test pattern 0xa7
932
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
933
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
934
wrote 10485760/10485760 bytes at offset 104857600
935
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
936
937
# Write test pattern 0x13
938
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
939
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
940
wrote 10485760/10485760 bytes at offset 3298534883328
941
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
942
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
943
944
# Open dev
945
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
946
-# Set dev owner
947
-sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
948
# Read test pattern 0x91
949
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
950
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
951
read 10485760/10485760 bytes at offset 104857600
952
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
953
954
# Read test pattern 0x5e
955
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
956
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
957
read 10485760/10485760 bytes at offset 3298534883328
958
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
959
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-sha224.img --size 4194304MB
960
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
961
# Open dev
962
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
963
-# Set dev owner
964
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
965
# Write test pattern 0xa7
966
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
967
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
968
wrote 10485760/10485760 bytes at offset 104857600
969
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
970
971
# Write test pattern 0x13
972
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
973
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
974
wrote 10485760/10485760 bytes at offset 3298534883328
975
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
976
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
977
978
# Open dev
979
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
980
-# Set dev owner
981
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
982
# Read test pattern 0x91
983
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
984
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
985
read 10485760/10485760 bytes at offset 104857600
986
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
987
988
# Read test pattern 0x5e
989
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
990
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
991
read 10485760/10485760 bytes at offset 3298534883328
992
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
993
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha224.img', fmt=luks size=4398046
994
995
# Open dev
996
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
997
-# Set dev owner
998
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
999
# Write test pattern 0xa7
1000
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1001
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1002
wrote 10485760/10485760 bytes at offset 104857600
1003
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1004
1005
# Write test pattern 0x13
1006
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1007
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1008
wrote 10485760/10485760 bytes at offset 3298534883328
1009
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1010
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1011
1012
# Open dev
1013
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha224.img qiotest-145-aes-256-xts-plain64-sha224
1014
-# Set dev owner
1015
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1016
# Read test pattern 0x91
1017
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1018
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1019
read 10485760/10485760 bytes at offset 104857600
1020
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1021
1022
# Read test pattern 0x5e
1023
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1024
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha224
1025
read 10485760/10485760 bytes at offset 3298534883328
1026
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1027
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB
1028
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
1029
# Open dev
1030
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
1031
-# Set dev owner
1032
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1033
# Write test pattern 0xa7
1034
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1035
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1036
wrote 10485760/10485760 bytes at offset 104857600
1037
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1038
1039
# Write test pattern 0x13
1040
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1041
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1042
wrote 10485760/10485760 bytes at offset 3298534883328
1043
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1044
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1045
1046
# Open dev
1047
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
1048
-# Set dev owner
1049
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1050
# Read test pattern 0x91
1051
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1052
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1053
read 10485760/10485760 bytes at offset 104857600
1054
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1055
1056
# Read test pattern 0x5e
1057
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1058
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1059
read 10485760/10485760 bytes at offset 3298534883328
1060
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1061
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046
1062
1063
# Open dev
1064
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
1065
-# Set dev owner
1066
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1067
# Write test pattern 0xa7
1068
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1069
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1070
wrote 10485760/10485760 bytes at offset 104857600
1071
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1072
1073
# Write test pattern 0x13
1074
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1075
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1076
wrote 10485760/10485760 bytes at offset 3298534883328
1077
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1078
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1079
1080
# Open dev
1081
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
1082
-# Set dev owner
1083
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1084
# Read test pattern 0x91
1085
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1086
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1087
read 10485760/10485760 bytes at offset 104857600
1088
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1089
1090
# Read test pattern 0x5e
1091
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1092
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
1093
read 10485760/10485760 bytes at offset 3298534883328
1094
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1095
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-sha384.img --size 4194304MB
1096
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
1097
# Open dev
1098
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
1099
-# Set dev owner
1100
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1101
# Write test pattern 0xa7
1102
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1103
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1104
wrote 10485760/10485760 bytes at offset 104857600
1105
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1106
1107
# Write test pattern 0x13
1108
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1109
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1110
wrote 10485760/10485760 bytes at offset 3298534883328
1111
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1112
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1113
1114
# Open dev
1115
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
1116
-# Set dev owner
1117
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1118
# Read test pattern 0x91
1119
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1120
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1121
read 10485760/10485760 bytes at offset 104857600
1122
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1123
1124
# Read test pattern 0x5e
1125
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1126
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1127
read 10485760/10485760 bytes at offset 3298534883328
1128
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1129
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha384.img', fmt=luks size=4398046
1130
1131
# Open dev
1132
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
1133
-# Set dev owner
1134
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1135
# Write test pattern 0xa7
1136
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1137
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1138
wrote 10485760/10485760 bytes at offset 104857600
1139
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1140
1141
# Write test pattern 0x13
1142
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1143
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1144
wrote 10485760/10485760 bytes at offset 3298534883328
1145
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1146
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1147
1148
# Open dev
1149
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha384.img qiotest-145-aes-256-xts-plain64-sha384
1150
-# Set dev owner
1151
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1152
# Read test pattern 0x91
1153
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1154
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1155
read 10485760/10485760 bytes at offset 104857600
1156
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1157
1158
# Read test pattern 0x5e
1159
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1160
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha384
1161
read 10485760/10485760 bytes at offset 3298534883328
1162
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1163
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-sha512.img --size 4194304MB
1164
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
1165
# Open dev
1166
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
1167
-# Set dev owner
1168
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1169
# Write test pattern 0xa7
1170
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1171
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1172
wrote 10485760/10485760 bytes at offset 104857600
1173
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1174
1175
# Write test pattern 0x13
1176
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1177
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1178
wrote 10485760/10485760 bytes at offset 3298534883328
1179
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1180
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1181
1182
# Open dev
1183
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
1184
-# Set dev owner
1185
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1186
# Read test pattern 0x91
1187
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1188
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1189
read 10485760/10485760 bytes at offset 104857600
1190
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1191
1192
# Read test pattern 0x5e
1193
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1194
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1195
read 10485760/10485760 bytes at offset 3298534883328
1196
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1197
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha512.img', fmt=luks size=4398046
1198
1199
# Open dev
1200
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
1201
-# Set dev owner
1202
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1203
# Write test pattern 0xa7
1204
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1205
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1206
wrote 10485760/10485760 bytes at offset 104857600
1207
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1208
1209
# Write test pattern 0x13
1210
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1211
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1212
wrote 10485760/10485760 bytes at offset 3298534883328
1213
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1214
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1215
1216
# Open dev
1217
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha512.img qiotest-145-aes-256-xts-plain64-sha512
1218
-# Set dev owner
1219
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1220
# Read test pattern 0x91
1221
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1222
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1223
read 10485760/10485760 bytes at offset 104857600
1224
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1225
1226
# Read test pattern 0x5e
1227
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1228
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha512
1229
read 10485760/10485760 bytes at offset 3298534883328
1230
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1231
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img --size 4194304MB
1232
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
1233
# Open dev
1234
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
1235
-# Set dev owner
1236
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1237
# Write test pattern 0xa7
1238
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1239
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1240
wrote 10485760/10485760 bytes at offset 104857600
1241
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1242
1243
# Write test pattern 0x13
1244
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1245
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1246
wrote 10485760/10485760 bytes at offset 3298534883328
1247
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1248
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1249
1250
# Open dev
1251
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
1252
-# Set dev owner
1253
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1254
# Read test pattern 0x91
1255
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1256
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1257
read 10485760/10485760 bytes at offset 104857600
1258
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1259
1260
# Read test pattern 0x5e
1261
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1262
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1263
read 10485760/10485760 bytes at offset 3298534883328
1264
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1265
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img', fmt=luks size=4398
1266
1267
# Open dev
1268
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
1269
-# Set dev owner
1270
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1271
# Write test pattern 0xa7
1272
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1273
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1274
wrote 10485760/10485760 bytes at offset 104857600
1275
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1276
1277
# Write test pattern 0x13
1278
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1279
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1280
wrote 10485760/10485760 bytes at offset 3298534883328
1281
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1282
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1283
1284
# Open dev
1285
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-ripemd160.img qiotest-145-aes-256-xts-plain64-ripemd160
1286
-# Set dev owner
1287
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1288
# Read test pattern 0x91
1289
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1290
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1291
read 10485760/10485760 bytes at offset 104857600
1292
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1293
1294
# Read test pattern 0x5e
1295
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1296
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-ripemd160
1297
read 10485760/10485760 bytes at offset 3298534883328
1298
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1299
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB
1300
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
1301
# Open dev
1302
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
1303
-# Set dev owner
1304
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1305
# Write test pattern 0xa7
1306
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1307
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1308
wrote 10485760/10485760 bytes at offset 104857600
1309
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1310
1311
# Write test pattern 0x13
1312
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1313
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1314
wrote 10485760/10485760 bytes at offset 3298534883328
1315
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1316
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1317
1318
# Open dev
1319
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
1320
-# Set dev owner
1321
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1322
# Read test pattern 0x91
1323
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1324
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1325
read 10485760/10485760 bytes at offset 104857600
1326
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1327
1328
# Read test pattern 0x5e
1329
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1330
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
1331
read 10485760/10485760 bytes at offset 3298534883328
1332
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1333
@@ -XXX,XX +XXX,XX @@ sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots
1334
sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - --iter-time 10 TEST_DIR/passwd.txt
1335
# Open dev
1336
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
1337
-# Set dev owner
1338
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1339
# Write test pattern 0xa7
1340
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1341
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1342
wrote 10485760/10485760 bytes at offset 104857600
1343
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1344
1345
# Write test pattern 0x13
1346
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1347
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1348
wrote 10485760/10485760 bytes at offset 3298534883328
1349
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1350
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1351
1352
# Open dev
1353
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
1354
-# Set dev owner
1355
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1356
# Read test pattern 0x91
1357
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1358
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1359
read 10485760/10485760 bytes at offset 104857600
1360
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1361
1362
# Read test pattern 0x5e
1363
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1364
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1365
read 10485760/10485760 bytes at offset 3298534883328
1366
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1367
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=
1368
1369
# Open dev
1370
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
1371
-# Set dev owner
1372
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1373
# Write test pattern 0xa7
1374
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1375
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1376
wrote 10485760/10485760 bytes at offset 104857600
1377
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1378
1379
# Write test pattern 0x13
1380
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1381
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1382
wrote 10485760/10485760 bytes at offset 3298534883328
1383
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1384
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1385
1386
# Open dev
1387
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
1388
-# Set dev owner
1389
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1390
# Read test pattern 0x91
1391
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1392
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1393
read 10485760/10485760 bytes at offset 104857600
1394
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1395
1396
# Read test pattern 0x5e
1397
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1398
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
1399
read 10485760/10485760 bytes at offset 3298534883328
1400
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1401
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img --size 4194304MB
1402
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
1403
# Open dev
1404
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
1405
-# Set dev owner
1406
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1407
# Write test pattern 0xa7
1408
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1409
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1410
wrote 10485760/10485760 bytes at offset 104857600
1411
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1412
1413
# Write test pattern 0x13
1414
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1415
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1416
wrote 10485760/10485760 bytes at offset 3298534883328
1417
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1418
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1419
1420
# Open dev
1421
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
1422
-# Set dev owner
1423
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1424
# Read test pattern 0x91
1425
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1426
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1427
read 10485760/10485760 bytes at offset 104857600
1428
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1429
1430
# Read test pattern 0x5e
1431
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1432
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1433
read 10485760/10485760 bytes at offset 3298534883328
1434
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1435
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img', fmt=luks size=439804
1436
1437
# Open dev
1438
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
1439
-# Set dev owner
1440
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1441
# Write test pattern 0xa7
1442
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1443
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1444
wrote 10485760/10485760 bytes at offset 104857600
1445
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1446
1447
# Write test pattern 0x13
1448
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1449
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1450
wrote 10485760/10485760 bytes at offset 3298534883328
1451
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1452
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1453
1454
# Open dev
1455
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-auto-sha1.img qiotest-145-aes-256-cbc-essiv-auto-sha1
1456
-# Set dev owner
1457
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1458
# Read test pattern 0x91
1459
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1460
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1461
read 10485760/10485760 bytes at offset 104857600
1462
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1463
1464
# Read test pattern 0x5e
1465
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1466
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-auto-sha1
1467
read 10485760/10485760 bytes at offset 3298534883328
1468
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1469
@@ -XXX,XX +XXX,XX @@ truncate TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img --size 4194304MB
1470
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
1471
# Open dev
1472
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
1473
-# Set dev owner
1474
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1475
# Write test pattern 0xa7
1476
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1477
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1478
wrote 10485760/10485760 bytes at offset 104857600
1479
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1480
1481
# Write test pattern 0x13
1482
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1483
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1484
wrote 10485760/10485760 bytes at offset 3298534883328
1485
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1486
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1487
1488
# Open dev
1489
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
1490
-# Set dev owner
1491
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1492
# Read test pattern 0x91
1493
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1494
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1495
read 10485760/10485760 bytes at offset 104857600
1496
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1497
1498
# Read test pattern 0x5e
1499
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1500
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1501
read 10485760/10485760 bytes at offset 3298534883328
1502
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1503
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img', fmt=luks size=43
1504
1505
# Open dev
1506
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
1507
-# Set dev owner
1508
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1509
# Write test pattern 0xa7
1510
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1511
qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1512
wrote 10485760/10485760 bytes at offset 104857600
1513
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1514
1515
# Write test pattern 0x13
1516
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1517
qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1518
wrote 10485760/10485760 bytes at offset 3298534883328
1519
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1520
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 3298534883328
1521
1522
# Open dev
1523
sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha256-sha1.img qiotest-145-aes-256-cbc-plain64-sha256-sha1
1524
-# Set dev owner
1525
-sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1526
# Read test pattern 0x91
1527
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1528
qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1529
read 10485760/10485760 bytes at offset 104857600
1530
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1531
1532
# Read test pattern 0x5e
1533
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1534
qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha256-sha1
1535
read 10485760/10485760 bytes at offset 3298534883328
1536
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1537
--
1538
1.8.3.1
1539
1540
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
A user may specify a relative path for accessing qemu, qemu-img, etc.
4
through environment variables ($QEMU_PROG and friends) or a symlink.
5
6
If a test decides to change its working directory, relative paths will
7
cease to work, however. Work around this by making all of the paths to
8
programs that should undergo testing absolute. Besides "realpath", we
9
also have to use "type -p" to support programs in $PATH.
10
11
As a side effect, this fixes specifying these programs as symlinks for
12
out-of-tree builds: Before, you would have to create two symlinks, one
13
in the build and one in the source tree (the first one for common.config
14
to find, the second one for the iotest to use). Now it is sufficient to
15
create one in the build tree because common.config will resolve it.
16
17
Reported-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Message-id: 20170702150510.23276-2-mreitz@redhat.com
20
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Tested-by: Eric Blake <eblake@redhat.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
tests/qemu-iotests/common.config | 11 +++++++++++
25
1 file changed, 11 insertions(+)
26
27
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/qemu-iotests/common.config
30
+++ b/tests/qemu-iotests/common.config
31
@@ -XXX,XX +XXX,XX @@ if [ -z "$QEMU_VXHS_PROG" ]; then
32
export QEMU_VXHS_PROG="`set_prog_path qnio_server`"
33
fi
34
35
+export QEMU_PROG=$(realpath -- "$(type -p "$QEMU_PROG")")
36
+export QEMU_IMG_PROG=$(realpath -- "$(type -p "$QEMU_IMG_PROG")")
37
+export QEMU_IO_PROG=$(realpath -- "$(type -p "$QEMU_IO_PROG")")
38
+export QEMU_NBD_PROG=$(realpath -- "$(type -p "$QEMU_NBD_PROG")")
39
+
40
+# This program is not built as part of qemu but (possibly) provided by the
41
+# system, so it may not be present at all
42
+if [ -n "$QEMU_VXHS_PROG" ]; then
43
+ export QEMU_VXHS_PROG=$(realpath -- "$(type -p "$QEMU_VXHS_PROG")")
44
+fi
45
+
46
_qemu_wrapper()
47
{
48
(
49
--
50
1.8.3.1
51
52
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Message-id: 20170702150510.23276-3-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/126 | 105 +++++++++++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/126.out | 23 ++++++++++
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 129 insertions(+)
12
create mode 100755 tests/qemu-iotests/126
13
create mode 100644 tests/qemu-iotests/126.out
14
15
diff --git a/tests/qemu-iotests/126 b/tests/qemu-iotests/126
16
new file mode 100755
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/qemu-iotests/126
20
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
22
+#
23
+# Tests handling of colons in filenames (which may be confused with protocol
24
+# prefixes)
25
+#
26
+# Copyright (C) 2017 Red Hat, Inc.
27
+#
28
+# This program is free software; you can redistribute it and/or modify
29
+# it under the terms of the GNU General Public License as published by
30
+# the Free Software Foundation; either version 2 of the License, or
31
+# (at your option) any later version.
32
+#
33
+# This program is distributed in the hope that it will be useful,
34
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36
+# GNU General Public License for more details.
37
+#
38
+# You should have received a copy of the GNU General Public License
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
40
+#
41
+
42
+# creator
43
+owner=mreitz@redhat.com
44
+
45
+seq="$(basename $0)"
46
+echo "QA output created by $seq"
47
+
48
+here="$PWD"
49
+status=1    # failure is the default!
50
+
51
+# get standard environment, filters and checks
52
+. ./common.rc
53
+. ./common.filter
54
+
55
+# Needs backing file support
56
+_supported_fmt qcow qcow2 qed vmdk
57
+# This is the default protocol (and we want to test the difference between
58
+# colons which separate a protocol prefix from the rest and colons which are
59
+# just part of the filename, so we cannot test protocols which require a prefix)
60
+_supported_proto file
61
+_supported_os Linux
62
+
63
+echo
64
+echo '=== Testing plain files ==='
65
+echo
66
+
67
+# A colon after a slash is not a protocol prefix separator
68
+TEST_IMG="$TEST_DIR/a:b.$IMGFMT" _make_test_img 64M
69
+_rm_test_img "$TEST_DIR/a:b.$IMGFMT"
70
+
71
+# But if you want to be really sure, you can do this
72
+TEST_IMG="file:$TEST_DIR/a:b.$IMGFMT" _make_test_img 64M
73
+_rm_test_img "$TEST_DIR/a:b.$IMGFMT"
74
+
75
+
76
+echo
77
+echo '=== Testing relative backing filename resolution ==='
78
+echo
79
+
80
+BASE_IMG="$TEST_DIR/image:base.$IMGFMT"
81
+TOP_IMG="$TEST_DIR/image:top.$IMGFMT"
82
+
83
+TEST_IMG=$BASE_IMG _make_test_img 64M
84
+TEST_IMG=$TOP_IMG _make_test_img -b ./image:base.$IMGFMT
85
+
86
+# The default cluster size depends on the image format
87
+TEST_IMG=$TOP_IMG _img_info | grep -v 'cluster_size'
88
+
89
+_rm_test_img "$BASE_IMG"
90
+_rm_test_img "$TOP_IMG"
91
+
92
+
93
+# Do another test where we access both top and base without any slash in them
94
+echo
95
+pushd "$TEST_DIR" >/dev/null
96
+
97
+BASE_IMG="base.$IMGFMT"
98
+TOP_IMG="file:image:top.$IMGFMT"
99
+
100
+TEST_IMG=$BASE_IMG _make_test_img 64M
101
+TEST_IMG=$TOP_IMG _make_test_img -b "$BASE_IMG"
102
+
103
+TEST_IMG=$TOP_IMG _img_info | grep -v 'cluster_size'
104
+
105
+_rm_test_img "$BASE_IMG"
106
+_rm_test_img "image:top.$IMGFMT"
107
+
108
+popd >/dev/null
109
+
110
+# Note that we could also do the same test with BASE_IMG=file:image:base.$IMGFMT
111
+# -- but behavior for that case is a bit strange. Protocol-prefixed paths are
112
+# in a sense always absolute paths, so such paths will never be combined with
113
+# the path of the overlay. But since "image:base.$IMGFMT" is actually a
114
+# relative path, it will always be evaluated relative to qemu's CWD (but not
115
+# relative to the overlay!). While this is more or less intended, it is still
116
+# pretty strange and thus not something that is tested here.
117
+# (The root of the issue is the use of a relative path with a protocol prefix.
118
+# This may always give you weird results because in one sense, qemu considers
119
+# such paths absolute, whereas in another, they are still relative.)
120
+
121
+
122
+# success, all done
123
+echo '*** done'
124
+rm -f $seq.full
125
+status=0
126
diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out
127
new file mode 100644
128
index XXXXXXX..XXXXXXX
129
--- /dev/null
130
+++ b/tests/qemu-iotests/126.out
131
@@ -XXX,XX +XXX,XX @@
132
+QA output created by 126
133
+
134
+=== Testing plain files ===
135
+
136
+Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864
137
+Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864
138
+
139
+=== Testing relative backing filename resolution ===
140
+
141
+Formatting 'TEST_DIR/image:base.IMGFMT', fmt=IMGFMT size=67108864
142
+Formatting 'TEST_DIR/image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=./image:base.IMGFMT
143
+image: TEST_DIR/image:top.IMGFMT
144
+file format: IMGFMT
145
+virtual size: 64M (67108864 bytes)
146
+backing file: ./image:base.IMGFMT (actual path: TEST_DIR/./image:base.IMGFMT)
147
+
148
+Formatting 'base.IMGFMT', fmt=IMGFMT size=67108864
149
+Formatting 'file:image:top.IMGFMT', fmt=IMGFMT size=67108864 backing_file=base.IMGFMT
150
+image: ./image:top.IMGFMT
151
+file format: IMGFMT
152
+virtual size: 64M (67108864 bytes)
153
+backing file: base.IMGFMT (actual path: ./base.IMGFMT)
154
+*** done
155
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
156
index XXXXXXX..XXXXXXX 100644
157
--- a/tests/qemu-iotests/group
158
+++ b/tests/qemu-iotests/group
159
@@ -XXX,XX +XXX,XX @@
160
122 rw auto
161
123 rw auto quick
162
124 rw auto backing
163
+126 rw auto backing
164
128 rw auto quick
165
129 rw auto quick
166
130 rw auto quick
167
--
168
1.8.3.1
169
170
diff view generated by jsdifflib