1
The following changes since commit 59a568b57848b10e8a44518a889323f12ccdd8f4:
1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190222-pull-request' into staging (2019-02-25 12:49:07 +0000)
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1b967e9f348d48788a2ab481d45398b80ce71fa6:
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block (2019-02-25 15:16:57 +0100)
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- Block graph change fixes (avoid loops, cope with non-tree graphs)
16
- Fix resize (extending) of short overlays
17
- bdrv_set_aio_context() related fixes
17
- nvme: introduce PMR support from NVMe 1.4 spec
18
- HMP snapshot commands: Use only tag, not the ID to identify snapshots
18
- qemu-storage-daemon: Fix non-string --object properties
19
- qmeu-img, commit: Error path fixes
20
- block/nvme: Build fix for gcc 9
21
- MAINTAINERS updates
22
- Fix various issues with bdrv_refresh_filename()
23
- Fix various iotests
24
- Include LUKS overhead in qemu-img measure for qcow2
25
- A fix for vmdk's image creation interface
26
19
27
----------------------------------------------------------------
20
----------------------------------------------------------------
28
Alberto Garcia (2):
21
Alberto Garcia (1):
29
commit: Replace commit_top_bs on failure after deleting the block job
22
qcow2: Add incompatibility note between backing files and raw external data files
30
qcow2: Assert that L2 table offsets fit in the L1 table
31
23
32
Daniel Henrique Barboza (3):
24
Andrzej Jakowski (1):
33
block/snapshot.c: eliminate use of ID input in snapshot operations
25
nvme: introduce PMR support from NVMe 1.4 spec
34
block/snapshot: remove bdrv_snapshot_delete_by_id_or_name
35
qcow2-snapshot: remove redundant find_snapshot_by_id_and_name call
36
26
37
Daniel P. Berrangé (1):
27
Kevin Wolf (12):
38
qemu-img: fix error reporting for -object
28
block: Add flags to BlockDriver.bdrv_co_truncate()
29
block: Add flags to bdrv(_co)_truncate()
30
block-backend: Add flags to blk_truncate()
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: truncate: Don't make backing file data visible
35
iotests: Filter testfiles out in filter_img_info()
36
iotests: Test committing to short backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
39
40
40
Denis Plotnikov (1):
41
Paolo Bonzini (1):
41
block: don't set the same context
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
42
43
43
Jeff Cody (2):
44
docs/interop/qcow2.txt | 3 +
44
MAINTAINERS: Replace myself with John Snow for block jobs
45
hw/block/nvme.h | 2 +
45
MAINTAINERS: Remove myself as block maintainer
46
include/block/block.h | 5 +-
47
include/block/block_int.h | 10 +-
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
49
include/qom/object_interfaces.h | 16 +++
50
include/sysemu/block-backend.h | 2 +-
51
block.c | 3 +-
52
block/block-backend.c | 4 +-
53
block/commit.c | 4 +-
54
block/crypto.c | 7 +-
55
block/file-posix.c | 6 +-
56
block/file-win32.c | 2 +-
57
block/gluster.c | 1 +
58
block/io.c | 43 ++++++-
59
block/iscsi.c | 2 +-
60
block/mirror.c | 2 +-
61
block/nfs.c | 3 +-
62
block/parallels.c | 6 +-
63
block/qcow.c | 4 +-
64
block/qcow2-cluster.c | 2 +-
65
block/qcow2-refcount.c | 2 +-
66
block/qcow2.c | 73 +++++++++--
67
block/qed.c | 3 +-
68
block/raw-format.c | 6 +-
69
block/rbd.c | 1 +
70
block/sheepdog.c | 4 +-
71
block/ssh.c | 2 +-
72
block/vdi.c | 2 +-
73
block/vhdx-log.c | 2 +-
74
block/vhdx.c | 6 +-
75
block/vmdk.c | 8 +-
76
block/vpc.c | 2 +-
77
blockdev.c | 2 +-
78
hw/block/nvme.c | 109 ++++++++++++++++
79
qemu-img.c | 2 +-
80
qemu-io-cmds.c | 2 +-
81
qemu-storage-daemon.c | 4 +-
82
qom/object_interfaces.c | 31 +++++
83
qom/qom-qmp-cmds.c | 24 +---
84
tests/test-block-iothread.c | 9 +-
85
tests/qemu-iotests/iotests.py | 5 +-
86
hw/block/Makefile.objs | 2 +-
87
hw/block/trace-events | 4 +
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
46
96
47
Kevin Wolf (14):
48
block-backend: Make blk_inc/dec_in_flight public
49
virtio-blk: Increase in_flight for request restart BH
50
nbd: Restrict connection_co reentrance
51
io: Make qio_channel_yield() interruptible
52
io: Remove redundant read/write_coroutine assignments
53
nbd: Move nbd_read_eof() to nbd/client.c
54
nbd: Use low-level QIOChannel API in nbd_read_eof()
55
nbd: Increase bs->in_flight during AioContext switch
56
block: Don't poll in bdrv_set_aio_context()
57
block: Fix AioContext switch for drained node
58
test-bdrv-drain: AioContext switch in drained section
59
block: Use normal drain for bdrv_set_aio_context()
60
aio-posix: Assert that aio_poll() is always called in home thread
61
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block
62
97
63
Max Reitz (42):
64
block: Use bdrv_refresh_filename() to pull
65
block: Use children list in bdrv_refresh_filename
66
block: Skip implicit nodes for filename info
67
block: Add BDS.auto_backing_file
68
block: Respect backing bs in bdrv_refresh_filename
69
iotests.py: Add filter_imgfmt()
70
iotests.py: Add node_info()
71
iotests: Add test for backing file overrides
72
block: Make path_combine() return the path
73
block: bdrv_get_full_backing_filename_from_...'s ret. val.
74
block: bdrv_get_full_backing_filename's ret. val.
75
block: Add bdrv_make_absolute_filename()
76
block: Fix bdrv_find_backing_image()
77
block: Add bdrv_dirname()
78
blkverify: Make bdrv_dirname() return NULL
79
quorum: Make bdrv_dirname() return NULL
80
block/nbd: Make bdrv_dirname() return NULL
81
block/nfs: Implement bdrv_dirname()
82
block: Use bdrv_dirname() for relative filenames
83
iotests: Add quorum case to test 110
84
block: Add strong_runtime_opts to BlockDriver
85
block: Add BlockDriver.bdrv_gather_child_options
86
block: Generically refresh runtime options
87
block: Purify .bdrv_refresh_filename()
88
block: Do not copy exact_filename from format file
89
block/nvme: Fix bdrv_refresh_filename()
90
block/curl: Harmonize option defaults
91
block/curl: Implement bdrv_refresh_filename()
92
block/null: Generate filename even with latency-ns
93
block: BDS options may lack the "driver" option
94
iotests: Test json:{} filenames of internal BDSs
95
iotests: Re-add filename filters
96
iotests: Fix 237 for Python 2.x
97
iotests: Remove superfluous rm from 232
98
iotests: Fix 232 for LUKS
99
iotests: Fix 207 to use QMP filters for qmp_log
100
iotests.py: Add is_str()
101
iotests.py: Filter filename in any string value
102
iotests: Filter SSH paths
103
iotests: Let 045 be run concurrently
104
iotests.py: s/_/-/g on keys in qmp_log()
105
iotests: Skip 211 on insufficient memory
106
107
Stefan Hajnoczi (2):
108
qcow2: include LUKS payload overhead in qemu-img measure
109
iotests: add LUKS payload overhead to 178 qemu-img measure test
110
111
Thomas Huth (1):
112
block/nvme: Remove QEMU_PACKED from naturally aligned NVMeRegs struct
113
114
Vladimir Sementsov-Ogievskiy (3):
115
block: improve should_update_child
116
block: fix bdrv_check_perm for non-tree subgraph
117
tests: add test-bdrv-graph-mod
118
119
yuchenlin (1):
120
vmdk: false positive of compat6 with hwversion not set
121
122
block/nbd-client.h | 1 +
123
include/block/block.h | 16 +-
124
include/block/block_int.h | 53 +++-
125
include/block/nbd.h | 3 +-
126
include/block/snapshot.h | 3 -
127
include/io/channel.h | 9 +-
128
include/sysemu/block-backend.h | 2 +
129
nbd/nbd-internal.h | 19 --
130
block.c | 597 +++++++++++++++++++++++++++------------
131
block/blkdebug.c | 70 ++---
132
block/blklogwrites.c | 33 +--
133
block/blkverify.c | 29 +-
134
block/block-backend.c | 4 +-
135
block/commit.c | 7 +-
136
block/crypto.c | 8 +
137
block/curl.c | 55 +++-
138
block/gluster.c | 19 ++
139
block/iscsi.c | 18 ++
140
block/mirror.c | 3 +-
141
block/nbd-client.c | 36 ++-
142
block/nbd.c | 46 +--
143
block/nfs.c | 54 ++--
144
block/null.c | 32 ++-
145
block/nvme.c | 29 +-
146
block/qapi.c | 16 +-
147
block/qcow.c | 14 +-
148
block/qcow2-cluster.c | 3 +
149
block/qcow2-snapshot.c | 5 -
150
block/qcow2.c | 89 +++++-
151
block/qed.c | 7 +-
152
block/quorum.c | 71 +++--
153
block/raw-format.c | 11 +-
154
block/rbd.c | 14 +
155
block/replication.c | 10 +-
156
block/sheepdog.c | 12 +
157
block/snapshot.c | 25 +-
158
block/ssh.c | 12 +
159
block/throttle.c | 7 +
160
block/vhdx-log.c | 1 +
161
block/vmdk.c | 46 ++-
162
block/vpc.c | 7 +
163
block/vvfat.c | 12 +
164
block/vxhs.c | 11 +
165
blockdev.c | 8 +
166
hw/block/virtio-blk.c | 4 +
167
io/channel.c | 22 +-
168
nbd/client.c | 52 +++-
169
qemu-img.c | 64 +++--
170
tests/test-bdrv-drain.c | 32 +++
171
tests/test-bdrv-graph-mod.c | 198 +++++++++++++
172
util/aio-posix.c | 3 +-
173
MAINTAINERS | 22 +-
174
hmp-commands.hx | 32 ++-
175
scripts/qemu.py | 5 +-
176
tests/Makefile.include | 2 +
177
tests/qemu-iotests/045 | 2 +-
178
tests/qemu-iotests/051.out | 8 +-
179
tests/qemu-iotests/051.pc.out | 8 +-
180
tests/qemu-iotests/110 | 29 +-
181
tests/qemu-iotests/110.out | 9 +-
182
tests/qemu-iotests/178 | 8 +
183
tests/qemu-iotests/178.out.qcow2 | 24 ++
184
tests/qemu-iotests/206.out | 56 ++--
185
tests/qemu-iotests/207 | 10 +-
186
tests/qemu-iotests/207.out | 18 +-
187
tests/qemu-iotests/210 | 5 +-
188
tests/qemu-iotests/210.out | 28 +-
189
tests/qemu-iotests/211 | 9 +-
190
tests/qemu-iotests/211.out | 26 +-
191
tests/qemu-iotests/212 | 5 +-
192
tests/qemu-iotests/212.out | 44 +--
193
tests/qemu-iotests/213 | 5 +-
194
tests/qemu-iotests/213.out | 46 +--
195
tests/qemu-iotests/224 | 139 +++++++++
196
tests/qemu-iotests/224.out | 18 ++
197
tests/qemu-iotests/228 | 239 ++++++++++++++++
198
tests/qemu-iotests/228.out | 84 ++++++
199
tests/qemu-iotests/232 | 5 +-
200
tests/qemu-iotests/237 | 7 +-
201
tests/qemu-iotests/237.out | 54 ++--
202
tests/qemu-iotests/common.rc | 1 +
203
tests/qemu-iotests/group | 2 +
204
tests/qemu-iotests/iotests.py | 36 ++-
205
83 files changed, 2191 insertions(+), 697 deletions(-)
206
create mode 100644 tests/test-bdrv-graph-mod.c
207
create mode 100755 tests/qemu-iotests/224
208
create mode 100644 tests/qemu-iotests/224.out
209
create mode 100755 tests/qemu-iotests/228
210
create mode 100644 tests/qemu-iotests/228.out
211
diff view generated by jsdifflib
Deleted patch
1
From: Jeff Cody <jcody@redhat.com>
2
1
3
I'll not be involved with day-to-day qemu development, and John
4
Snow is a block jobs wizard. Have him take over block job
5
maintainership duties.
6
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Acked-by: John Snow <jsnow@redhat.com>
9
Message-Id: <d56d7c6592e7d68aa72764e9616878394bffbc14.1537984851.git.jcody@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
MAINTAINERS | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: include/scsi/*
20
F: scsi/*
21
22
Block Jobs
23
-M: Jeff Cody <jcody@redhat.com>
24
+M: John Snow <jsnow@redhat.com>
25
L: qemu-block@nongnu.org
26
S: Supported
27
F: blockjob.c
28
@@ -XXX,XX +XXX,XX @@ F: block/commit.c
29
F: block/stream.c
30
F: block/mirror.c
31
F: qapi/job.json
32
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
33
+T: git https://github.com/jnsnow/qemu.git jobs
34
35
Block QAPI, monitor, command line
36
M: Markus Armbruster <armbru@redhat.com>
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Jeff Cody <jcody@redhat.com>
2
1
3
I'll not be involved in day-to-day qemu development. Remove myself as
4
maintainer from the remainder of the network block drivers, and revert
5
them to the general block layer maintainership.
6
7
Move 'sheepdog' to the 'Odd Fixes' support level.
8
9
For VHDX, added my personal email address as a maintainer, as I can
10
answer questions or send the occassional bug fix. Leaving it as
11
'Supported', instead of 'Odd Fixes', because I think the rest of the
12
block layer maintainers and developers will upkeep it as well, if
13
needed.
14
15
Signed-off-by: Jeff Cody <jcody@redhat.com>
16
Acked-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <63e205cb84c8f0a10c1bc6d5d6856d72ceb56e41.1537984851.git.jcody@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
MAINTAINERS | 18 +++---------------
21
1 file changed, 3 insertions(+), 15 deletions(-)
22
23
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
25
--- a/MAINTAINERS
26
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ F: block/vmdk.c
28
29
RBD
30
M: Josh Durgin <jdurgin@redhat.com>
31
-M: Jeff Cody <jcody@redhat.com>
32
L: qemu-block@nongnu.org
33
S: Supported
34
F: block/rbd.c
35
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
36
37
Sheepdog
38
M: Liu Yuan <namei.unix@gmail.com>
39
-M: Jeff Cody <jcody@redhat.com>
40
L: qemu-block@nongnu.org
41
-S: Supported
42
+L: sheepdog@lists.wpkg.org
43
+S: Odd Fixes
44
F: block/sheepdog.c
45
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
46
47
VHDX
48
-M: Jeff Cody <jcody@redhat.com>
49
+M: Jeff Cody <codyprime@gmail.com>
50
L: qemu-block@nongnu.org
51
S: Supported
52
F: block/vhdx*
53
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
54
55
VDI
56
M: Stefan Weil <sw@weilnetz.de>
57
@@ -XXX,XX +XXX,XX @@ F: docs/interop/nbd.txt
58
T: git https://repo.or.cz/qemu/ericb.git nbd
59
60
NFS
61
-M: Jeff Cody <jcody@redhat.com>
62
M: Peter Lieven <pl@kamp.de>
63
L: qemu-block@nongnu.org
64
S: Maintained
65
F: block/nfs.c
66
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
67
68
SSH
69
M: Richard W.M. Jones <rjones@redhat.com>
70
-M: Jeff Cody <jcody@redhat.com>
71
L: qemu-block@nongnu.org
72
S: Supported
73
F: block/ssh.c
74
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
75
76
CURL
77
-M: Jeff Cody <jcody@redhat.com>
78
L: qemu-block@nongnu.org
79
S: Supported
80
F: block/curl.c
81
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
82
83
GLUSTER
84
-M: Jeff Cody <jcody@redhat.com>
85
L: qemu-block@nongnu.org
86
S: Supported
87
F: block/gluster.c
88
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
89
90
Null Block Driver
91
M: Fam Zheng <fam@euphon.net>
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
1
3
At this moment, QEMU attempts to create/load/delete snapshots
4
by using either an ID (id_str) or a name. The problem is that the code
5
isn't consistent of whether the entered argument is an ID or a name,
6
causing unexpected behaviors.
7
8
For example, when creating snapshots via savevm <arg>, what happens is that
9
"arg" is treated as both name and id_str. In a guest without snapshots, create
10
a single snapshot via savevm:
11
12
(qemu) savevm 0
13
(qemu) info snapshots
14
List of snapshots present on all disks:
15
ID TAG VM SIZE DATE VM CLOCK
16
-- 0 741M 2018-07-31 13:39:56 00:41:25.313
17
18
A snapshot with name "0" is created. ID is hidden from the user, but the
19
ID is a non-zero integer that starts at "1". Thus, this snapshot has
20
id_str=1, TAG="0". Creating a second snapshot with arg = 1, the first one
21
is deleted:
22
23
(qemu) savevm 1
24
(qemu) info snapshots
25
List of snapshots present on all disks:
26
ID TAG VM SIZE DATE VM CLOCK
27
-- 1 741M 2018-07-31 13:42:14 00:41:55.252
28
29
What happened?
30
31
- when creating the second snapshot, a verification is done inside
32
bdrv_all_delete_snapshot to delete any existing snapshots that matches an
33
string argument. Here, the code calls bdrv_all_delete_snapshot("1", ...);
34
35
- bdrv_all_delete_snapshot calls bdrv_snapshot_find(..., "1") for each
36
BlockDriverState of the guest. And this is where things goes tilting:
37
bdrv_snapshot_find does a search by both id_str and name. It finds
38
out that there is a snapshot that has id_str = 1, stores a reference
39
to the snapshot in the sn_info pointer and then returns match found;
40
41
- since a match was found, a call to bdrv_snapshot_delete_by_id_or_name() is
42
made. This function ignores the pointer written by bdrv_snapshot_find. Instead,
43
it deletes the snapshot using bdrv_snapshot_delete() calling it first with
44
id_str = 1. If it fails to delete, then it calls it again with name = 1.
45
46
- after all that, QEMU creates the new snapshot, that has id_str = 1 and
47
name = 1. The user is left wondering that happened with the first snapshot
48
created. Similar bugs can be triggered when using loadvm and delvm.
49
50
Before contemplating discarding the use of ID input in these operations,
51
I've searched the code of what would be the implications. My findings
52
are:
53
54
- the RBD and Sheepdog drivers don't care. Both uses the 'name' field as
55
key in their logic, making id_str = name when appropriate.
56
replay-snapshot.c does not make any special use of id_str;
57
58
- qcow2 uses id_str as an unique identifier but it is automatically
59
calculated, not being influenced by user input. Other than that, there are
60
no distinguish operations made only with id_str;
61
62
- in blockdev.c, the delete operation uses a match of both id_str AND
63
name. Given that id_str is either a copy of 'name' or auto-generated,
64
we're fine here.
65
66
This gives motivation to not consider ID as a valid user input in HMP
67
commands - sticking with 'name' input only is more consistent. To
68
accomplish that, the following changes were made in this patch:
69
70
- bdrv_snapshot_find() does not match for id_str anymore, only 'name'. The
71
function is called in save_snapshot(), load_snapshot(), bdrv_all_delete_snapshot()
72
and bdrv_all_find_snapshot(). This change makes the search function more
73
predictable and does not change the behavior of any underlying code that uses
74
these affected functions, which are related to HMP (which is fine) and the
75
main loop inside vl.c (which doesn't care about it anyways);
76
77
- bdrv_all_delete_snapshot() does not call bdrv_snapshot_delete_by_id_or_name
78
anymore. Instead, it uses the pointer returned by bdrv_snapshot_find to
79
erase the snapshot with the exact match of id_str an name. This function
80
is called in save_snapshot and hmp_delvm, thus this change produces the
81
intended effect;
82
83
- documentation changes to reflect the new behavior. I consider this to
84
be an API fix instead of an API change - the user was already creating
85
snapshots using 'name', but now he/she will also enjoy a consistent
86
behavior.
87
88
Ideally we would get rid of the id_str field entirely, but this would have
89
repercussions on existing snapshots. Another day perhaps.
90
91
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
92
Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
93
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
94
---
95
block/snapshot.c | 5 +++--
96
hmp-commands.hx | 32 ++++++++++++++++++++------------
97
2 files changed, 23 insertions(+), 14 deletions(-)
98
99
diff --git a/block/snapshot.c b/block/snapshot.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/snapshot.c
102
+++ b/block/snapshot.c
103
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
104
}
105
for (i = 0; i < nb_sns; i++) {
106
sn = &sn_tab[i];
107
- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
108
+ if (!strcmp(sn->name, name)) {
109
*sn_info = *sn;
110
ret = 0;
111
break;
112
@@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
113
aio_context_acquire(ctx);
114
if (bdrv_can_snapshot(bs) &&
115
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
116
- ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
117
+ ret = bdrv_snapshot_delete(bs, snapshot->id_str,
118
+ snapshot->name, err);
119
}
120
aio_context_release(ctx);
121
if (ret < 0) {
122
diff --git a/hmp-commands.hx b/hmp-commands.hx
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hmp-commands.hx
125
+++ b/hmp-commands.hx
126
@@ -XXX,XX +XXX,XX @@ ETEXI
127
{
128
.name = "savevm",
129
.args_type = "name:s?",
130
- .params = "[tag|id]",
131
- .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
132
+ .params = "tag",
133
+ .help = "save a VM snapshot. If no tag is provided, a new snapshot is created",
134
.cmd = hmp_savevm,
135
},
136
137
STEXI
138
-@item savevm [@var{tag}|@var{id}]
139
+@item savevm @var{tag}
140
@findex savevm
141
Create a snapshot of the whole virtual machine. If @var{tag} is
142
provided, it is used as human readable identifier. If there is already
143
-a snapshot with the same tag or ID, it is replaced. More info at
144
+a snapshot with the same tag, it is replaced. More info at
145
@ref{vm_snapshots}.
146
+
147
+Since 4.0, savevm stopped allowing the snapshot id to be set, accepting
148
+only @var{tag} as parameter.
149
ETEXI
150
151
{
152
.name = "loadvm",
153
.args_type = "name:s",
154
- .params = "tag|id",
155
- .help = "restore a VM snapshot from its tag or id",
156
+ .params = "tag",
157
+ .help = "restore a VM snapshot from its tag",
158
.cmd = hmp_loadvm,
159
.command_completion = loadvm_completion,
160
},
161
162
STEXI
163
-@item loadvm @var{tag}|@var{id}
164
+@item loadvm @var{tag}
165
@findex loadvm
166
Set the whole virtual machine to the snapshot identified by the tag
167
-@var{tag} or the unique snapshot ID @var{id}.
168
+@var{tag}.
169
+
170
+Since 4.0, loadvm stopped accepting snapshot id as parameter.
171
ETEXI
172
173
{
174
.name = "delvm",
175
.args_type = "name:s",
176
- .params = "tag|id",
177
- .help = "delete a VM snapshot from its tag or id",
178
+ .params = "tag",
179
+ .help = "delete a VM snapshot from its tag",
180
.cmd = hmp_delvm,
181
.command_completion = delvm_completion,
182
},
183
184
STEXI
185
-@item delvm @var{tag}|@var{id}
186
+@item delvm @var{tag}
187
@findex delvm
188
-Delete the snapshot identified by @var{tag} or @var{id}.
189
+Delete the snapshot identified by @var{tag}.
190
+
191
+Since 4.0, delvm stopped deleting snapshots by snapshot id, accepting
192
+only @var{tag} as parameter.
193
ETEXI
194
195
{
196
--
197
2.20.1
198
199
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
1
3
After the previous patch, the only instance of this function left
4
is inside qemu-img.c.
5
6
qemu-img is using it inside the 'img_snapshot' function to delete
7
snapshots in the SNAPSHOT_DELETE case, based on a "snapshot_name"
8
string that refers to the tag, not ID, of the QEMUSnapshotInfo struct.
9
This can be verified by checking the SNAPSHOT_CREATE case that
10
comes shortly before SNAPSHOT_DELETE. In that case, the same
11
"snapshot_name" variable is being strcpy to the 'name' field
12
of the QEMUSnapshotInfo struct sn:
13
14
pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
15
16
Based on that, it is unlikely that "snapshot_name" might contain
17
an "id" in SNAPSHOT_DELETE.
18
19
This patch changes SNAPSHOT_DELETE to use snapshot_find() and
20
snapshot_delete() instead of bdrv_snapshot_delete_by_id_or_name.
21
After that, there is no instances left of bdrv_snapshot_delete_by_id_or_name
22
in the code, so it is safe to remove it entirely.
23
24
Suggested-by: Murilo Opsfelder Araujo <muriloo@linux.ibm.com>
25
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
28
include/block/snapshot.h | 3 ---
29
block/snapshot.c | 20 --------------------
30
qemu-img.c | 15 +++++++++++----
31
3 files changed, 11 insertions(+), 27 deletions(-)
32
33
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/snapshot.h
36
+++ b/include/block/snapshot.h
37
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
38
const char *snapshot_id,
39
const char *name,
40
Error **errp);
41
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
42
- const char *id_or_name,
43
- Error **errp);
44
int bdrv_snapshot_list(BlockDriverState *bs,
45
QEMUSnapshotInfo **psn_info);
46
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
47
diff --git a/block/snapshot.c b/block/snapshot.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/snapshot.c
50
+++ b/block/snapshot.c
51
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
52
return ret;
53
}
54
55
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
56
- const char *id_or_name,
57
- Error **errp)
58
-{
59
- int ret;
60
- Error *local_err = NULL;
61
-
62
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
63
- if (ret == -ENOENT || ret == -EINVAL) {
64
- error_free(local_err);
65
- local_err = NULL;
66
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
67
- }
68
-
69
- if (ret < 0) {
70
- error_propagate(errp, local_err);
71
- }
72
- return ret;
73
-}
74
-
75
int bdrv_snapshot_list(BlockDriverState *bs,
76
QEMUSnapshotInfo **psn_info)
77
{
78
diff --git a/qemu-img.c b/qemu-img.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/qemu-img.c
81
+++ b/qemu-img.c
82
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
83
break;
84
85
case SNAPSHOT_DELETE:
86
- bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
87
- if (err) {
88
- error_reportf_err(err, "Could not delete snapshot '%s': ",
89
- snapshot_name);
90
+ ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
91
+ if (ret < 0) {
92
+ error_report("Could not delete snapshot '%s': snapshot not "
93
+ "found", snapshot_name);
94
ret = 1;
95
+ } else {
96
+ ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
97
+ if (ret < 0) {
98
+ error_reportf_err(err, "Could not delete snapshot '%s': ",
99
+ snapshot_name);
100
+ ret = 1;
101
+ }
102
}
103
break;
104
}
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
1
3
In qcow2_snapshot_create there is the following code block:
4
5
/* Generate an ID */
6
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
7
8
/* Check that the ID is unique */
9
if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
10
return -EEXIST;
11
}
12
13
find_new_snapshot_id cycles through all snapshots, getting the id_str
14
as an unsigned long int, calculating the max id_max value of all the
15
existing id_strs and writing in the id_str pointer id_max + 1:
16
17
for(i = 0; i < s->nb_snapshots; i++) {
18
sn = s->snapshots + i;
19
id = strtoul(sn->id_str, NULL, 10);
20
if (id > id_max)
21
id_max = id;
22
}
23
snprintf(id_str, id_str_size, "%lu", id_max + 1);
24
25
Here, sn_info->id_str will have the unique value id_max + 1. Right
26
after that, find_snapshot_by_id_and_name is called with
27
id = sn_info->id_str and name = NULL. This will cause the function
28
to execute the following:
29
30
} else if (id) {
31
for (i = 0; i < s->nb_snapshots; i++) {
32
if (!strcmp(s->snapshots[i].id_str, id)) {
33
return i;
34
}
35
}
36
}
37
38
In short, we're searching the existing snapshots to see if sn_info->id_str
39
matches any existing id, right after we set in the previous line a
40
sn_info->id_str value that is already unique.
41
42
The first code block goes way back to commit 585f8587ad, a 2006 commit from
43
Fabrice Bellard that simply says "new qcow2 disk image format". No more
44
info is provided about this logic in any subsequent commits that moved
45
this code block around.
46
47
I can't say about the original design, but the current logic is redundant.
48
bdrv_snapshot_create is called in aio_context lock, forbidding any
49
concurrent call to accidentally create a new snapshot between
50
the find_new_snapshot_id and find_snapshot_by_id_and_name calls. What
51
we're ending up doing is to cycle through the snapshots two times
52
for no viable reason.
53
54
This patch eliminates the redundancy by removing the 'id is unique'
55
check that calls find_snapshot_by_id_and_name.
56
57
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
58
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
59
---
60
block/qcow2-snapshot.c | 5 -----
61
1 file changed, 5 deletions(-)
62
63
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/qcow2-snapshot.c
66
+++ b/block/qcow2-snapshot.c
67
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
68
/* Generate an ID */
69
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
70
71
- /* Check that the ID is unique */
72
- if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
73
- return -EEXIST;
74
- }
75
-
76
/* Populate sn with passed data */
77
sn->id_str = g_strdup(sn_info->id_str);
78
sn->name = g_strdup(sn_info->name);
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
Deleted patch
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
2
1
3
Adds a fast path on aio context setting preventing
4
unnecessary context setting routine.
5
Also, it prevents issues with cyclic walk of child
6
bds-es appeared because of registering aio walking
7
notifiers:
8
9
Call stack:
10
11
0 __GI_raise
12
1 __GI_abort
13
2 __assert_fail_base
14
3 __GI___assert_fail
15
4 bdrv_detach_aio_context (bs=0x55f54d65c000) <<<
16
5 bdrv_detach_aio_context (bs=0x55f54fc8a800)
17
6 bdrv_set_aio_context (bs=0x55f54fc8a800, ...)
18
7 block_job_attached_aio_context
19
8 bdrv_attach_aio_context (bs=0x55f54d65c000, ...) <<<
20
9 bdrv_set_aio_context (bs=0x55f54d65c000)
21
10 blk_set_aio_context
22
11 virtio_blk_data_plane_stop
23
12 virtio_bus_stop_ioeventfd
24
13 virtio_vmstate_change
25
14 vm_state_notify (running=0, state=RUN_STATE_SHUTDOWN)
26
15 do_vm_stop (state=RUN_STATE_SHUTDOWN, send_stop=true)
27
16 vm_stop (state=RUN_STATE_SHUTDOWN)
28
17 main_loop_should_exit
29
18 main_loop
30
19 main
31
32
This can happen because of "new" context attachment to VM disk bds.
33
When attaching a new context the corresponding aio context handler is
34
called for each of aio_notifiers registered on the VM disk bds context.
35
Among those handlers, there is the block_job_attached_aio_context handler
36
which sets a new aio context for the block job bds. When doing so,
37
the old context is detached from all the block job bds children and one of
38
them is the VM disk bds, serving as backing store for the blockjob bds,
39
although the VM disk bds is actually the initializer of that process.
40
Since the VM disk bds is protected with walking_aio_notifiers flag
41
from double processing in recursive calls, the assert fires.
42
43
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
44
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
45
---
46
block.c | 4 ++++
47
1 file changed, 4 insertions(+)
48
49
diff --git a/block.c b/block.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block.c
52
+++ b/block.c
53
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
54
{
55
AioContext *ctx = bdrv_get_aio_context(bs);
56
57
+ if (ctx == new_context) {
58
+ return;
59
+ }
60
+
61
aio_disable_external(ctx);
62
bdrv_parent_drained_begin(bs, NULL, false);
63
bdrv_drain(bs); /* ensure there are no in-flight requests */
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
If there's an error in commit_start() then the block job must be
3
Backing files and raw external data files are mutually exclusive.
4
deleted before replacing commit_top_bs, otherwise it will fail because
4
The documentation of the raw external data bit (in autoclear_features)
5
of lack of permissions. This happens since the permission system was
5
already indicates that, but we should also mention it on the other
6
introduced in 8dfba2797761d8a43744e4e6571c8175e448a478.
6
side.
7
7
8
Fortunately this bug doesn't seem to be possible to reproduce at the
8
Suggested-by: Eric Blake <eblake@redhat.com>
9
moment without changing the code.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
13
---
14
block/commit.c | 4 +++-
14
docs/interop/qcow2.txt | 3 +++
15
1 file changed, 3 insertions(+), 1 deletion(-)
15
1 file changed, 3 insertions(+)
16
16
17
diff --git a/block/commit.c b/block/commit.c
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/commit.c
19
--- a/docs/interop/qcow2.txt
20
+++ b/block/commit.c
20
+++ b/docs/interop/qcow2.txt
21
@@ -XXX,XX +XXX,XX @@ fail:
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
22
if (s->top) {
22
is stored (NB: The string is not null terminated). 0 if the
23
blk_unref(s->top);
23
image doesn't have a backing file.
24
}
24
25
+ job_early_fail(&s->common.job);
25
+ Note: backing files are incompatible with raw external data
26
+ /* commit_top_bs has to be replaced after deleting the block job,
26
+ files (auto-clear feature bit 1).
27
+ * otherwise this would fail because of lack of permissions. */
27
+
28
if (commit_top_bs) {
28
16 - 19: backing_file_size
29
bdrv_replace_node(commit_top_bs, top, &error_abort);
29
Length of the backing file name in bytes. Must not be
30
}
30
longer than 1023 bytes. Undefined if the image doesn't have
31
- job_early_fail(&s->common.job);
32
}
33
34
35
--
31
--
36
2.20.1
32
2.25.3
37
33
38
34
diff view generated by jsdifflib
Deleted patch
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
1
3
Error reporting for user_creatable_add_opts_foreach was changed so that
4
it no longer called 'error_report_err' in:
5
6
commit 7e1e0c11127bde81cff260fc6859690435c509d6
7
Author: Markus Armbruster <armbru@redhat.com>
8
Date: Wed Oct 17 10:26:43 2018 +0200
9
10
qom: Clean up error reporting in user_creatable_add_opts_foreach()
11
12
Some callers were updated to pass in "&error_fatal" but all the ones in
13
qemu-img were left passing NULL. As a result all errors went to
14
/dev/null instead of being reported to the user.
15
16
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
17
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Reviewed-by: Markus Armbruster <armbru@redhat.com>
19
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
qemu-img.c | 26 +++++++++++++-------------
23
1 file changed, 13 insertions(+), 13 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
31
if (qemu_opts_foreach(&qemu_object_opts,
32
user_creatable_add_opts_foreach,
33
- NULL, NULL)) {
34
+ NULL, &error_fatal)) {
35
goto fail;
36
}
37
38
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
39
40
if (qemu_opts_foreach(&qemu_object_opts,
41
user_creatable_add_opts_foreach,
42
- NULL, NULL)) {
43
+ NULL, &error_fatal)) {
44
return 1;
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
48
49
if (qemu_opts_foreach(&qemu_object_opts,
50
user_creatable_add_opts_foreach,
51
- NULL, NULL)) {
52
+ NULL, &error_fatal)) {
53
return 1;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
57
58
if (qemu_opts_foreach(&qemu_object_opts,
59
user_creatable_add_opts_foreach,
60
- NULL, NULL)) {
61
+ NULL, &error_fatal)) {
62
ret = 2;
63
goto out4;
64
}
65
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
66
67
if (qemu_opts_foreach(&qemu_object_opts,
68
user_creatable_add_opts_foreach,
69
- NULL, NULL)) {
70
+ NULL, &error_fatal)) {
71
goto fail_getopt;
72
}
73
74
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
75
76
if (qemu_opts_foreach(&qemu_object_opts,
77
user_creatable_add_opts_foreach,
78
- NULL, NULL)) {
79
+ NULL, &error_fatal)) {
80
return 1;
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
84
85
if (qemu_opts_foreach(&qemu_object_opts,
86
user_creatable_add_opts_foreach,
87
- NULL, NULL)) {
88
+ NULL, &error_fatal)) {
89
return 1;
90
}
91
92
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
93
94
if (qemu_opts_foreach(&qemu_object_opts,
95
user_creatable_add_opts_foreach,
96
- NULL, NULL)) {
97
+ NULL, &error_fatal)) {
98
return 1;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
102
103
if (qemu_opts_foreach(&qemu_object_opts,
104
user_creatable_add_opts_foreach,
105
- NULL, NULL)) {
106
+ NULL, &error_fatal)) {
107
return 1;
108
}
109
110
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
111
112
if (qemu_opts_foreach(&qemu_object_opts,
113
user_creatable_add_opts_foreach,
114
- NULL, NULL)) {
115
+ NULL, &error_fatal)) {
116
return 1;
117
}
118
119
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
120
121
if (qemu_opts_foreach(&qemu_object_opts,
122
user_creatable_add_opts_foreach,
123
- NULL, NULL)) {
124
+ NULL, &error_fatal)) {
125
ret = -1;
126
goto out_no_progress;
127
}
128
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
129
130
if (qemu_opts_foreach(&qemu_object_opts,
131
user_creatable_add_opts_foreach,
132
- NULL, NULL)) {
133
+ NULL, &error_fatal)) {
134
ret = -1;
135
goto out;
136
}
137
@@ -XXX,XX +XXX,XX @@ static int img_measure(int argc, char **argv)
138
139
if (qemu_opts_foreach(&qemu_object_opts,
140
user_creatable_add_opts_foreach,
141
- NULL, NULL)) {
142
+ NULL, &error_fatal)) {
143
goto out;
144
}
145
146
--
147
2.20.1
148
149
diff view generated by jsdifflib
Deleted patch
1
For some users of BlockBackends, just increasing the in_flight counter
2
is easier than implementing separate handlers in BlockDevOps. Make the
3
helper functions for this public.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
include/sysemu/block-backend.h | 2 ++
8
block/block-backend.c | 4 ++--
9
2 files changed, 4 insertions(+), 2 deletions(-)
10
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
15
@@ -XXX,XX +XXX,XX @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
16
int blk_co_flush(BlockBackend *blk);
17
int blk_flush(BlockBackend *blk);
18
int blk_commit_all(void);
19
+void blk_inc_in_flight(BlockBackend *blk);
20
+void blk_dec_in_flight(BlockBackend *blk);
21
void blk_drain(BlockBackend *blk);
22
void blk_drain_all(void);
23
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
24
diff --git a/block/block-backend.c b/block/block-backend.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/block-backend.c
27
+++ b/block/block-backend.c
28
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
29
return bdrv_make_zero(blk->root, flags);
30
}
31
32
-static void blk_inc_in_flight(BlockBackend *blk)
33
+void blk_inc_in_flight(BlockBackend *blk)
34
{
35
atomic_inc(&blk->in_flight);
36
}
37
38
-static void blk_dec_in_flight(BlockBackend *blk)
39
+void blk_dec_in_flight(BlockBackend *blk)
40
{
41
atomic_dec(&blk->in_flight);
42
aio_wait_kick();
43
--
44
2.20.1
45
46
diff view generated by jsdifflib
1
qio_channel_yield() now updates ioc->read_write/coroutine and calls
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
qio_channel_set_aio_fd_handlers(), so the code in the handlers has
3
become redundant and can be removed.
4
2
5
This does not make a difference in intermediate states because
3
Test 244 checks the expected behavior of qcow2 external data files
6
aio_co_wake() really enters the coroutine immediately here: These
4
with respect to zero and discarded clusters. Filesystems however
7
handlers are never run in coroutine context, and we're in the right
5
are free to ignore discard requests, and this seems to be the
8
AioContext because qio_channel_attach_aio_context() asserts that the
6
case for overlayfs. Relax the tests to skip checks on the
9
handlers are inactive.
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
10
9
11
To make these conditions more obvious, assert the right AioContext.
10
This fixes docker tests on RHEL8.
12
11
13
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
12
Cc: Kevin Wolf <kwolf@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
17
---
16
io/channel.c | 12 ++++++------
18
tests/qemu-iotests/244 | 10 ++++++++--
17
1 file changed, 6 insertions(+), 6 deletions(-)
19
tests/qemu-iotests/244.out | 9 ++++++---
20
2 files changed, 14 insertions(+), 5 deletions(-)
18
21
19
diff --git a/io/channel.c b/io/channel.c
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
20
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
21
--- a/io/channel.c
53
--- a/tests/qemu-iotests/244.out
22
+++ b/io/channel.c
54
+++ b/tests/qemu-iotests/244.out
23
@@ -XXX,XX +XXX,XX @@ off_t qio_channel_io_seek(QIOChannel *ioc,
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
24
}
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
25
57
read 1048576/1048576 bytes at offset 1048576
26
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
27
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
59
-read 2097152/2097152 bytes at offset 2097152
28
-
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
29
static void qio_channel_restart_read(void *opaque)
61
read 1048576/1048576 bytes at offset 4194304
30
{
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
31
QIOChannel *ioc = opaque;
63
read 1048576/1048576 bytes at offset 5242880
32
Coroutine *co = ioc->read_coroutine;
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
33
65
read 4194304/4194304 bytes at offset 2097152
34
- ioc->read_coroutine = NULL;
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
35
- qio_channel_set_aio_fd_handlers(ioc);
67
36
+ /* Assert that aio_co_wake() reenters the coroutine directly */
68
-Images are identical.
37
+ assert(qemu_get_current_aio_context() ==
69
+read 1048576/1048576 bytes at offset 0
38
+ qemu_coroutine_get_aio_context(co));
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
39
aio_co_wake(co);
71
+read 1048576/1048576 bytes at offset 1048576
40
}
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
41
73
+read 3145728/3145728 bytes at offset 3145728
42
@@ -XXX,XX +XXX,XX @@ static void qio_channel_restart_write(void *opaque)
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
43
QIOChannel *ioc = opaque;
75
qcow2 file size after I/O: 327680
44
Coroutine *co = ioc->write_coroutine;
76
45
77
=== bdrv_co_block_status test for file and offset=0 ===
46
- ioc->write_coroutine = NULL;
47
- qio_channel_set_aio_fd_handlers(ioc);
48
+ /* Assert that aio_co_wake() reenters the coroutine directly */
49
+ assert(qemu_get_current_aio_context() ==
50
+ qemu_coroutine_get_aio_context(co));
51
aio_co_wake(co);
52
}
53
54
--
78
--
55
2.20.1
79
2.25.3
56
80
57
81
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
2
2
driver callbacks, and a supported_truncate_flags field in
3
If the backing file is overridden, this most probably does change the
3
BlockDriverState that allows drivers to advertise support for request
4
guest-visible data of a BDS. Therefore, we will need to consider this
4
flags in the context of truncate.
5
in bdrv_refresh_filename().
5
6
6
For now, we always pass 0 and no drivers declare support for any flag.
7
To see whether it has been overridden, we might want to compare
7
8
bs->backing_file and bs->backing->bs->filename. However,
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
bs->backing_file is changed by bdrv_set_backing_hd() (which is just used
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
to change the backing child at runtime, without modifying the image
11
header), so bs->backing_file most of the time simply contains a copy of
12
bs->backing->bs->filename anyway, so it is useless for such a
13
comparison.
14
15
This patch adds an auto_backing_file BDS field which contains the
16
backing file path as indicated by the image header, which is not changed
17
by bdrv_set_backing_hd().
18
19
Because of bdrv_refresh_filename() magic, however, a BDS's filename may
20
differ from what has been specified during bdrv_open(). Then, the
21
comparison between bs->auto_backing_file and bs->backing->bs->filename
22
may fail even though bs->backing was opened from bs->auto_backing_file.
23
To mitigate this, we can copy the real BDS's filename (after the whole
24
bdrv_open() and bdrv_refresh_filename() process) into
25
bs->auto_backing_file, if we know the former has been opened based on
26
the latter. This is only possible if no options modifying the backing
27
file's behavior have been specified, though. To simplify things, this
28
patch only copies the filename from the backing file if no options have
29
been specified for it at all.
30
31
Furthermore, there are cases where an overlay is created by qemu which
32
already contains a BDS's filename (e.g. in blockdev-snapshot-sync). We
33
do not need to worry about updating the overlay's bs->auto_backing_file
34
there, because we actually wrote a post-bdrv_refresh_filename() filename
35
into the image header.
36
37
So all in all, there will be false negatives where (as of a future
38
patch) bdrv_refresh_filename() will assume that the backing file differs
39
from what was specified in the image header, even though it really does
40
not. However, these cases should be limited to where (1) the user
41
actually did override something in the backing chain (e.g. by specifying
42
options for the backing file), or (2) the user executed a QMP command to
43
change some node's backing file (e.g. change-backing-file or
44
block-commit with @backing-file given) where the given filename does not
45
happen to coincide with qemu's idea of the backing BDS's filename.
46
47
Then again, (1) really is limited to -drive. With -blockdev or
48
blockdev-add, you have to adhere to the schema, so a user cannot give
49
partial "unimportant" options (e.g. by just setting backing.node-name
50
and leaving the rest to the image header). Therefore, trying to fix
51
this would mean trying to fix something for -drive only.
52
53
To improve on (2), we would need a full infrastructure to "canonicalize"
54
an arbitrary filename (+ options), so it can be compared against
55
another. That seems a bit over the top, considering that filenames
56
nowadays are there mostly for the user's entertainment.
57
58
Signed-off-by: Max Reitz <mreitz@redhat.com>
59
Reviewed-by: Eric Blake <eblake@redhat.com>
60
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
61
Message-id: 20190201192935.18394-5-mreitz@redhat.com
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
62
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
63
---
14
---
64
include/block/block_int.h | 4 ++++
15
include/block/block_int.h | 10 +++++++++-
65
block.c | 19 +++++++++++++++++++
16
block/crypto.c | 3 ++-
66
block/qcow.c | 7 +++++--
17
block/file-posix.c | 2 +-
67
block/qcow2.c | 10 +++++++---
18
block/file-win32.c | 2 +-
68
block/qed.c | 7 +++++--
19
block/gluster.c | 1 +
69
block/vmdk.c | 6 ++++--
20
block/io.c | 8 +++++++-
70
6 files changed, 44 insertions(+), 9 deletions(-)
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
71
31
72
diff --git a/include/block/block_int.h b/include/block/block_int.h
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
73
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
74
--- a/include/block/block_int.h
34
--- a/include/block/block_int.h
75
+++ b/include/block/block_int.h
35
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
*/
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
39
bool exact, PreallocMode prealloc,
40
- Error **errp);
41
+ BdrvRequestFlags flags, Error **errp);
42
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
44
bool has_variable_length;
76
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
77
char filename[PATH_MAX];
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
78
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
79
this file image */
48
unsigned int supported_zero_flags;
80
+ /* The backing filename indicated by the image header; if we ever
49
+ /*
81
+ * open this file, then this is replaced by the resulting BDS's
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
82
+ * filename (i.e. after a bdrv_refresh_filename() run). */
51
+ *
83
+ char auto_backing_file[PATH_MAX];
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
84
char backing_format[16]; /* if non-zero and backing_file exists */
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
85
54
+ * the operation must fail.
86
QDict *full_open_options;
55
+ */
87
diff --git a/block.c b/block.c
56
+ unsigned int supported_truncate_flags;
88
index XXXXXXX..XXXXXXX 100644
57
89
--- a/block.c
58
/* the following member gives a name to every node on the bs graph. */
90
+++ b/block.c
59
char node_name[32];
91
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
60
diff --git a/block/crypto.c b/block/crypto.c
92
char *bdref_key_dot;
61
index XXXXXXX..XXXXXXX 100644
93
const char *reference = NULL;
62
--- a/block/crypto.c
94
int ret = 0;
63
+++ b/block/crypto.c
95
+ bool implicit_backing = false;
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
96
BlockDriverState *backing_hd;
65
97
QDict *options;
66
static int coroutine_fn
98
QDict *tmp_parent_options = NULL;
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
99
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
68
- PreallocMode prealloc, Error **errp)
100
qobject_unref(options);
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
101
goto free_exit;
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
126
127
if (drv->bdrv_co_truncate) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
133
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
135
} else if (bs->file && drv->is_filter) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
102
} else {
137
} else {
103
+ if (qdict_size(options) == 0) {
138
diff --git a/block/iscsi.c b/block/iscsi.c
104
+ /* If the user specifies options that do not modify the
139
index XXXXXXX..XXXXXXX 100644
105
+ * backing file's behavior, we might still consider it the
140
--- a/block/iscsi.c
106
+ * implicit backing file. But it's easier this way, and
141
+++ b/block/iscsi.c
107
+ * just specifying some of the backing BDS's options is
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
108
+ * only possible with -drive anyway (otherwise the QAPI
143
109
+ * schema forces the user to specify everything). */
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
110
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
145
bool exact, PreallocMode prealloc,
111
+ }
146
- Error **errp)
112
+
147
+ BdrvRequestFlags flags, Error **errp)
113
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
148
{
114
&local_err);
149
IscsiLun *iscsilun = bs->opaque;
115
if (local_err) {
150
int64_t cur_length;
116
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
151
diff --git a/block/nfs.c b/block/nfs.c
117
}
152
index XXXXXXX..XXXXXXX 100644
118
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
153
--- a/block/nfs.c
119
154
+++ b/block/nfs.c
120
+ if (implicit_backing) {
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
121
+ bdrv_refresh_filename(backing_hd);
156
122
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
157
static int coroutine_fn
123
+ backing_hd->filename);
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
124
+ }
159
- PreallocMode prealloc, Error **errp)
125
+
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
126
/* Hook up the backing file link; drop our reference, bs owns the
161
+ Error **errp)
127
* backing_hd reference now */
162
{
128
bdrv_set_backing_hd(bs, backing_hd, &local_err);
163
NFSClient *client = bs->opaque;
129
@@ -XXX,XX +XXX,XX @@ int bdrv_change_backing_file(BlockDriverState *bs,
164
int ret;
130
if (ret == 0) {
131
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
132
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
133
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
134
+ backing_file ?: "");
135
}
136
return ret;
137
}
138
diff --git a/block/qcow.c b/block/qcow.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/qcow.c
141
+++ b/block/qcow.c
142
@@ -XXX,XX +XXX,XX @@
143
#include "qemu/module.h"
144
#include "qemu/option.h"
145
#include "qemu/bswap.h"
146
+#include "qemu/cutils.h"
147
#include <zlib.h>
148
#include "qapi/qmp/qdict.h"
149
#include "qapi/qmp/qstring.h"
150
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
151
goto fail;
152
}
153
ret = bdrv_pread(bs->file, header.backing_file_offset,
154
- bs->backing_file, len);
155
+ bs->auto_backing_file, len);
156
if (ret < 0) {
157
goto fail;
158
}
159
- bs->backing_file[len] = '\0';
160
+ bs->auto_backing_file[len] = '\0';
161
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
162
+ bs->auto_backing_file);
163
}
164
165
/* Disable migration when qcow images are used */
166
diff --git a/block/qcow2.c b/block/qcow2.c
165
diff --git a/block/qcow2.c b/block/qcow2.c
167
index XXXXXXX..XXXXXXX 100644
166
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
167
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
168
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
169
@@ -XXX,XX +XXX,XX @@ fail:
171
goto fail;
170
172
}
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
173
ret = bdrv_pread(bs->file, header.backing_file_offset,
172
bool exact, PreallocMode prealloc,
174
- bs->backing_file, len);
173
- Error **errp)
175
+ bs->auto_backing_file, len);
174
+ BdrvRequestFlags flags, Error **errp)
176
if (ret < 0) {
175
{
177
error_setg_errno(errp, -ret, "Could not read backing file name");
176
BDRVQcow2State *s = bs->opaque;
178
goto fail;
177
uint64_t old_length;
179
}
180
- bs->backing_file[len] = '\0';
181
- s->image_backing_file = g_strdup(bs->backing_file);
182
+ bs->auto_backing_file[len] = '\0';
183
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
184
+ bs->auto_backing_file);
185
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
186
}
187
188
/* Internal snapshots */
189
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
190
return -EINVAL;
191
}
192
193
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
194
+ backing_file ?: "");
195
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
196
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
197
198
diff --git a/block/qed.c b/block/qed.c
178
diff --git a/block/qed.c b/block/qed.c
199
index XXXXXXX..XXXXXXX 100644
179
index XXXXXXX..XXXXXXX 100644
200
--- a/block/qed.c
180
--- a/block/qed.c
201
+++ b/block/qed.c
181
+++ b/block/qed.c
202
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
203
}
183
int64_t offset,
204
184
bool exact,
205
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
185
PreallocMode prealloc,
206
- s->header.backing_filename_size, bs->backing_file,
186
+ BdrvRequestFlags flags,
207
- sizeof(bs->backing_file));
187
Error **errp)
208
+ s->header.backing_filename_size,
188
{
209
+ bs->auto_backing_file,
189
BDRVQEDState *s = bs->opaque;
210
+ sizeof(bs->auto_backing_file));
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
211
if (ret < 0) {
234
if (ret < 0) {
212
return ret;
235
return ret;
213
}
236
}
214
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
237
diff --git a/block/ssh.c b/block/ssh.c
215
+ bs->auto_backing_file);
238
index XXXXXXX..XXXXXXX 100644
216
239
--- a/block/ssh.c
217
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
240
+++ b/block/ssh.c
218
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
219
diff --git a/block/vmdk.c b/block/vmdk.c
242
220
index XXXXXXX..XXXXXXX 100644
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
221
--- a/block/vmdk.c
244
bool exact, PreallocMode prealloc,
222
+++ b/block/vmdk.c
245
- Error **errp)
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
246
+ BdrvRequestFlags flags, Error **errp)
224
ret = -EINVAL;
247
{
225
goto out;
248
BDRVSSHState *s = bs->opaque;
226
}
249
227
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
228
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
251
index XXXXXXX..XXXXXXX 100644
229
ret = -EINVAL;
252
--- a/tests/test-block-iothread.c
230
goto out;
253
+++ b/tests/test-block-iothread.c
231
}
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
232
255
233
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
256
static int coroutine_fn
234
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
235
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
258
- PreallocMode prealloc, Error **errp)
236
+ bs->auto_backing_file);
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
237
}
260
+ Error **errp)
238
261
{
239
out:
262
return 0;
263
}
240
--
264
--
241
2.20.1
265
2.25.3
242
266
243
267
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
2
4
3
Before this patch, bdrv_refresh_filename() is used in a pushing manner:
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Whenever the BDS graph is modified, the parents of the modified edges
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
are supposed to be updated (recursively upwards). However, that is
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
nonviable, considering that we want child changes not to concern
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
parents.
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
8
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Also, in the long run we want a pull model anyway: Here, we would have a
10
bdrv_filename() function which returns a BDS's filename, freshly
11
constructed.
12
13
This patch is an intermediate step. It adds bdrv_refresh_filename()
14
calls before every place a BDS.filename value is used. The only
15
exceptions are protocol drivers that use their own filename, which
16
clearly would not profit from refreshing that filename before.
17
18
Also, bdrv_get_encrypted_filename() is removed along the way (as a user
19
of BDS.filename), since it is completely unused.
20
21
In turn, all of the calls to bdrv_refresh_filename() before this patch
22
are removed, because we no longer have to call this function on graph
23
changes.
24
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
Message-id: 20190201192935.18394-2-mreitz@redhat.com
27
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
29
---
11
---
30
include/block/block.h | 1 -
12
include/block/block.h | 5 +++--
31
block.c | 31 +++++++++++++++----------------
13
block/block-backend.c | 2 +-
32
block/qapi.c | 4 ++++
14
block/crypto.c | 2 +-
33
block/raw-format.c | 1 +
15
block/io.c | 12 +++++++-----
34
block/replication.c | 2 --
16
block/parallels.c | 6 +++---
35
block/vhdx-log.c | 1 +
17
block/qcow.c | 4 ++--
36
block/vmdk.c | 6 ++++++
18
block/qcow2-refcount.c | 2 +-
37
blockdev.c | 8 ++++++++
19
block/qcow2.c | 15 +++++++++------
38
qemu-img.c | 11 +++++++++--
20
block/raw-format.c | 2 +-
39
9 files changed, 44 insertions(+), 21 deletions(-)
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
40
26
41
diff --git a/include/block/block.h b/include/block/block.h
27
diff --git a/include/block/block.h b/include/block/block.h
42
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block.h
29
--- a/include/block/block.h
44
+++ b/include/block/block.h
30
+++ b/include/block/block.h
45
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
46
int64_t *cluster_offset,
32
void bdrv_refresh_filename(BlockDriverState *bs);
47
int64_t *cluster_bytes);
33
48
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
49
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
35
- PreallocMode prealloc, Error **errp);
50
void bdrv_get_backing_filename(BlockDriverState *bs,
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
51
char *filename, int filename_size);
37
+ Error **errp);
52
void bdrv_get_full_backing_filename(BlockDriverState *bs,
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
53
diff --git a/block.c b/block.c
39
- PreallocMode prealloc, Error **errp);
54
index XXXXXXX..XXXXXXX 100644
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
55
--- a/block.c
41
56
+++ b/block.c
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
57
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
43
int64_t bdrv_getlength(BlockDriverState *bs);
58
void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
44
diff --git a/block/block-backend.c b/block/block-backend.c
59
Error **errp)
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
47
+++ b/block/block-backend.c
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
49
return -ENOMEDIUM;
50
}
51
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
54
}
55
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
60
+++ b/block/crypto.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
60
{
81
{
61
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
82
BlockDriverState *bs = child->bs;
62
+ char *backed;
83
BlockDriver *drv = bs->drv;
63
84
BdrvTrackedRequest req;
64
+ bdrv_refresh_filename(bs);
85
- BdrvRequestFlags flags = 0;
65
+
86
int64_t old_size, new_bytes;
66
+ backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
87
int ret;
67
bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
88
68
dest, sz, errp);
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
69
}
90
}
70
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
71
"node is used as backing hd of '%s'",
92
} else if (bs->file && drv->is_filter) {
72
bdrv_get_device_or_node_name(parent));
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
73
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
74
+ bdrv_refresh_filename(backing_hd);
75
+
76
parent->open_flags &= ~BDRV_O_NO_BACKING;
77
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
78
backing_hd->filename);
79
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
80
}
81
82
if (file != NULL) {
83
+ bdrv_refresh_filename(blk_bs(file));
84
filename = blk_bs(file)->filename;
85
} else {
95
} else {
86
/*
96
error_setg(errp, "Image format driver does not support resize");
87
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
97
ret = -ENOTSUP;
88
bdrv_unref(backing_hd);
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
89
}
99
int64_t offset;
90
100
bool exact;
91
- bdrv_refresh_filename(bs);
101
PreallocMode prealloc;
92
-
102
+ BdrvRequestFlags flags;
93
out:
103
Error **errp;
94
bdrv_refresh_limits(bs, NULL);
104
int ret;
95
}
105
} TruncateCo;
96
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
97
g_free(child_key_dot);
107
{
98
}
108
TruncateCo *tco = opaque;
99
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
100
- bdrv_refresh_filename(bs);
110
- tco->prealloc, tco->errp);
101
-
111
+ tco->prealloc, tco->flags, tco->errp);
102
/* Check if any unknown options were used */
112
aio_wait_kick();
103
if (qdict_size(options) != 0) {
113
}
104
const QDictEntry *entry = qdict_first(options);
114
105
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
106
if (local_err != NULL) {
116
- PreallocMode prealloc, Error **errp)
107
error_propagate(errp, local_err);
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
108
} else {
118
{
109
+ bdrv_refresh_filename(reopen_state->bs);
119
Coroutine *co;
110
error_setg(errp, "failed while preparing to reopen image '%s'",
120
TruncateCo tco = {
111
reopen_state->bs->filename);
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
112
}
226
}
113
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
114
/* success - we can delete the intermediate states, and link top->base */
228
new_file_size = allocation_start +
115
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
229
nb_new_data_clusters * s->cluster_size;
116
* we've figured out how they should work. */
230
/* Image file grows, so @exact does not matter */
117
- backing_file_str = backing_file_str ? backing_file_str : base->filename;
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
118
+ if (!backing_file_str) {
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
119
+ bdrv_refresh_filename(base);
233
+ errp);
120
+ backing_file_str = base->filename;
234
if (ret < 0) {
121
+ }
235
error_prepend(errp, "Failed to resize underlying file: ");
122
236
qcow2_free_clusters(bs, allocation_start,
123
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
124
/* Check whether we are allowed to switch c from top to base */
238
if (len < 0) {
125
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
239
return len;
126
return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP;
240
}
127
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
128
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
129
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
243
+ NULL);
130
-{
244
}
131
- if (bs->backing && bs->backing->bs->encrypted)
245
132
- return bs->backing_file;
246
if (offset_into_cluster(s, offset)) {
133
- else if (bs->encrypted)
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
134
- return bs->filename;
248
}
135
- else
249
136
- return NULL;
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
137
-}
251
- PREALLOC_MODE_OFF, &local_err);
138
-
252
+ PREALLOC_MODE_OFF, 0, &local_err);
139
void bdrv_get_backing_filename(BlockDriverState *bs,
253
if (ret < 0) {
140
char *filename, int filename_size)
254
error_report_err(local_err);
141
{
255
goto fail;
142
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
143
144
is_protocol = path_has_protocol(backing_file);
145
146
+ /* This will recursively refresh everything in the backing chain */
147
+ bdrv_refresh_filename(bs);
148
+
149
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
150
151
/* If either of the filename paths is actually a protocol, then
152
diff --git a/block/qapi.c b/block/qapi.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/qapi.c
155
+++ b/block/qapi.c
156
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
157
return NULL;
158
}
159
160
+ bdrv_refresh_filename(bs);
161
+
162
info = g_malloc0(sizeof(*info));
163
info->file = g_strdup(bs->filename);
164
info->ro = bs->read_only;
165
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
166
goto out;
167
}
168
169
+ bdrv_refresh_filename(bs);
170
+
171
info = g_new0(ImageInfo, 1);
172
info->filename = g_strdup(bs->filename);
173
info->format = g_strdup(bdrv_get_format_name(bs));
174
diff --git a/block/raw-format.c b/block/raw-format.c
256
diff --git a/block/raw-format.c b/block/raw-format.c
175
index XXXXXXX..XXXXXXX 100644
257
index XXXXXXX..XXXXXXX 100644
176
--- a/block/raw-format.c
258
--- a/block/raw-format.c
177
+++ b/block/raw-format.c
259
+++ b/block/raw-format.c
178
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
179
bs->file->bs->supported_zero_flags);
261
180
262
s->size = offset;
181
if (bs->probed && !bdrv_is_read_only(bs)) {
263
offset += s->offset;
182
+ bdrv_refresh_filename(bs->file->bs);
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
183
fprintf(stderr,
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
184
"WARNING: Image format was not specified for '%s' and probing "
266
}
185
"guessed raw.\n"
267
186
diff --git a/block/replication.c b/block/replication.c
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
187
index XXXXXXX..XXXXXXX 100644
188
--- a/block/replication.c
189
+++ b/block/replication.c
190
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
191
if (ret == 0) {
192
s->stage = BLOCK_REPLICATION_DONE;
193
194
- /* refresh top bs's filename */
195
- bdrv_refresh_filename(bs);
196
s->active_disk = NULL;
197
s->secondary_disk = NULL;
198
s->hidden_disk = NULL;
199
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
200
index XXXXXXX..XXXXXXX 100644
270
index XXXXXXX..XXXXXXX 100644
201
--- a/block/vhdx-log.c
271
--- a/block/vhdx-log.c
202
+++ b/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
203
@@ -XXX,XX +XXX,XX @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
204
274
goto exit;
205
if (logs.valid) {
275
}
206
if (bs->read_only) {
276
ret = bdrv_truncate(bs->file, new_file_size, false,
207
+ bdrv_refresh_filename(bs);
277
- PREALLOC_MODE_OFF, NULL);
208
ret = -EPERM;
278
+ PREALLOC_MODE_OFF, 0, NULL);
209
error_setg(errp,
279
if (ret < 0) {
210
"VHDX image file '%s' opened read-only, but "
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
211
diff --git a/block/vmdk.c b/block/vmdk.c
295
diff --git a/block/vmdk.c b/block/vmdk.c
212
index XXXXXXX..XXXXXXX 100644
296
index XXXXXXX..XXXXXXX 100644
213
--- a/block/vmdk.c
297
--- a/block/vmdk.c
214
+++ b/block/vmdk.c
298
+++ b/block/vmdk.c
215
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
216
extent->l1_table,
217
l1_size);
218
if (ret < 0) {
219
+ bdrv_refresh_filename(extent->file->bs);
220
error_setg_errno(errp, -ret,
221
"Could not read l1 table from extent '%s'",
222
extent->file->bs->filename);
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
224
extent->l1_backup_table,
225
l1_size);
226
if (ret < 0) {
227
+ bdrv_refresh_filename(extent->file->bs);
228
error_setg_errno(errp, -ret,
229
"Could not read l1 backup table from extent '%s'",
230
extent->file->bs->filename);
231
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
232
233
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
234
if (ret < 0) {
235
+ bdrv_refresh_filename(file->bs);
236
error_setg_errno(errp, -ret,
237
"Could not read header from file '%s'",
238
file->bs->filename);
239
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
240
241
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
242
if (ret < 0) {
243
+ bdrv_refresh_filename(file->bs);
244
error_setg_errno(errp, -ret,
245
"Could not read header from file '%s'",
246
file->bs->filename);
247
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
248
if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
249
!desc_file_path[0])
250
{
251
+ bdrv_refresh_filename(bs->file->bs);
252
error_setg(errp, "Cannot use relative extent paths with VMDK "
253
"descriptor file '%s'", bs->file->bs->filename);
254
return -EINVAL;
255
@@ -XXX,XX +XXX,XX @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
256
{
257
ImageInfo *info = g_new0(ImageInfo, 1);
258
259
+ bdrv_refresh_filename(extent->file->bs);
260
*info = (ImageInfo){
261
.filename = g_strdup(extent->file->bs->filename),
262
.format = g_strdup(extent->type),
263
diff --git a/blockdev.c b/blockdev.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/blockdev.c
266
+++ b/blockdev.c
267
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
268
error_setg_errno(errp, -size, "bdrv_getlength failed");
269
goto out;
270
}
300
}
271
+ bdrv_refresh_filename(state->old_bs);
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
272
bdrv_img_create(new_image_file, format,
302
ret = bdrv_truncate(s->extents[i].file, length, false,
273
state->old_bs->filename,
303
- PREALLOC_MODE_OFF, NULL);
274
state->old_bs->drv->format_name,
304
+ PREALLOC_MODE_OFF, 0, NULL);
275
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
305
if (ret < 0) {
276
goto out;
306
return ret;
277
}
278
assert(bdrv_get_aio_context(base_bs) == aio_context);
279
+ bdrv_refresh_filename(base_bs);
280
base_name = base_bs->filename;
281
}
282
283
@@ -XXX,XX +XXX,XX @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
284
goto out;
285
}
286
} else if (has_top && top) {
287
+ /* This strcmp() is just a shortcut, there is no need to
288
+ * refresh @bs's filename. If it mismatches,
289
+ * bdrv_find_backing_image() will do the refresh and may still
290
+ * return @bs. */
291
if (strcmp(bs->filename, top) != 0) {
292
top_bs = bdrv_find_backing_image(bs, top);
293
}
294
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
295
if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
296
assert(backup->format);
297
if (source) {
298
+ bdrv_refresh_filename(source);
299
bdrv_img_create(backup->target, backup->format, source->filename,
300
source->drv->format_name, NULL,
301
size, flags, false, &local_err);
302
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
303
break;
304
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
305
/* create new image with backing file */
306
+ bdrv_refresh_filename(source);
307
bdrv_img_create(arg->target, format,
308
source->filename,
309
source->drv->format_name,
310
diff --git a/qemu-img.c b/qemu-img.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/qemu-img.c
313
+++ b/qemu-img.c
314
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
315
BlockDriverState *file;
316
bool has_offset;
317
int64_t map;
318
+ char *filename = NULL;
319
320
/* As an optimization, we could cache the current range of unallocated
321
* clusters in each file of the chain, and avoid querying the same
322
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
323
324
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
325
326
+ if (file && has_offset) {
327
+ bdrv_refresh_filename(file);
328
+ filename = file->filename;
329
+ }
330
+
331
*e = (MapEntry) {
332
.start = offset,
333
.length = bytes,
334
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
335
.offset = map,
336
.has_offset = has_offset,
337
.depth = depth,
338
- .has_filename = file && has_offset,
339
- .filename = file && has_offset ? file->filename : NULL,
340
+ .has_filename = filename,
341
+ .filename = filename,
342
};
343
344
return 0;
345
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
346
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
347
}
307
}
348
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
349
+ bdrv_refresh_filename(bs);
309
index XXXXXXX..XXXXXXX 100644
350
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
310
--- a/tests/test-block-iothread.c
351
: bs->filename;
311
+++ b/tests/test-block-iothread.c
352
out_real_path = g_malloc(PATH_MAX);
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
353
--
334
--
354
2.20.1
335
2.25.3
355
336
356
337
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Now that node level interface bdrv_truncate() supports passing request
2
2
flags to the block driver, expose this on the BlockBackend level, too.
3
Make bdrv_get_full_backing_filename_from_filename() return an allocated
3
4
string instead of placing the result in a caller-provided buffer.
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Message-id: 20190201192935.18394-11-mreitz@redhat.com
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
include/block/block.h | 7 +++---
11
include/sysemu/block-backend.h | 2 +-
11
block.c | 53 ++++++++++++++++++++++++++++++-------------
12
block.c | 3 ++-
12
block/vmdk.c | 10 ++++----
13
block/block-backend.c | 4 ++--
13
qemu-img.c | 12 ++++------
14
block/commit.c | 4 ++--
14
4 files changed, 49 insertions(+), 33 deletions(-)
15
block/crypto.c | 2 +-
15
16
block/mirror.c | 2 +-
16
diff --git a/include/block/block.h b/include/block/block.h
17
block/qcow2.c | 4 ++--
17
index XXXXXXX..XXXXXXX 100644
18
block/qed.c | 2 +-
18
--- a/include/block/block.h
19
block/vdi.c | 2 +-
19
+++ b/include/block/block.h
20
block/vhdx.c | 4 ++--
20
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
21
block/vmdk.c | 6 +++---
21
char *filename, int filename_size);
22
block/vpc.c | 2 +-
22
void bdrv_get_full_backing_filename(BlockDriverState *bs,
23
blockdev.c | 2 +-
23
char *dest, size_t sz, Error **errp);
24
qemu-img.c | 2 +-
24
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
25
qemu-io-cmds.c | 2 +-
25
- const char *backing,
26
15 files changed, 22 insertions(+), 21 deletions(-)
26
- char *dest, size_t sz,
27
27
- Error **errp);
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
28
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
29
index XXXXXXX..XXXXXXX 100644
29
+ const char *backing,
30
--- a/include/sysemu/block-backend.h
30
+ Error **errp);
31
+++ b/include/sysemu/block-backend.h
31
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
32
int path_has_protocol(const char *path);
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
33
int path_is_absolute(const char *path);
34
int bytes);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
- PreallocMode prealloc, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
40
int64_t pos, int size);
34
diff --git a/block.c b/block.c
41
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
43
--- a/block.c
37
+++ b/block.c
44
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ fail:
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
39
return -EACCES;
46
int64_t size;
47
int ret;
48
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
51
+ &local_err);
52
if (ret < 0 && ret != -ENOTSUP) {
53
error_propagate(errp, local_err);
54
return ret;
55
diff --git a/block/block-backend.c b/block/block-backend.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/block-backend.c
58
+++ b/block/block-backend.c
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
40
}
60
}
41
61
42
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
43
- const char *backing,
63
- PreallocMode prealloc, Error **errp)
44
- char *dest, size_t sz,
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
45
- Error **errp)
46
+/*
47
+ * If @backing is empty, this function returns NULL without setting
48
+ * @errp. In all other cases, NULL will only be returned with @errp
49
+ * set.
50
+ *
51
+ * Therefore, a return value of NULL without @errp set means that
52
+ * there is no backing file; if @errp is set, there is one but its
53
+ * absolute filename cannot be generated.
54
+ */
55
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
56
+ const char *backing,
57
+ Error **errp)
58
{
65
{
59
- if (backing[0] == '\0' || path_has_protocol(backing) ||
66
if (!blk_is_available(blk)) {
60
- path_is_absolute(backing))
67
error_setg(errp, "No medium inserted");
61
- {
68
return -ENOMEDIUM;
62
- pstrcpy(dest, sz, backing);
69
}
63
+ if (backing[0] == '\0') {
70
64
+ return NULL;
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
65
+ } else if (path_has_protocol(backing) || path_is_absolute(backing)) {
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
66
+ return g_strdup(backing);
67
} else if (backed[0] == '\0' || strstart(backed, "json:", NULL)) {
68
error_setg(errp, "Cannot use relative backing file names for '%s'",
69
backed);
70
+ return NULL;
71
} else {
72
- path_combine_deprecated(dest, sz, backed, backing);
73
+ return path_combine(backed, backing);
74
}
75
}
73
}
76
74
77
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
78
Error **errp)
76
diff --git a/block/commit.c b/block/commit.c
79
{
77
index XXXXXXX..XXXXXXX 100644
80
char *backed;
78
--- a/block/commit.c
81
+ char *full_name;
79
+++ b/block/commit.c
82
+ Error *local_error = NULL;
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
83
81
}
84
bdrv_refresh_filename(bs);
82
85
83
if (base_len < len) {
86
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
87
- bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
88
- dest, sz, errp);
86
if (ret) {
89
+
87
goto out;
90
+ full_name = bdrv_get_full_backing_filename_from_filename(backed,
88
}
91
+ bs->backing_file,
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
92
+ &local_error);
90
* grow the backing file image if possible. If not possible,
93
+ if (full_name) {
91
* we must return an error */
94
+ pstrcpy(dest, sz, full_name);
92
if (length > backing_length) {
95
+ g_free(full_name);
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
96
+ } else if (local_error) {
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
97
+ error_propagate(errp, local_error);
95
&local_err);
98
+ } else if (sz > 0) {
96
if (ret < 0) {
99
+ *dest = '\0';
97
error_report_err(local_err);
100
+ }
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
101
}
108
}
102
109
103
void bdrv_register(BlockDriver *bdrv)
110
104
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
111
diff --git a/block/mirror.c b/block/mirror.c
105
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
112
index XXXXXXX..XXXXXXX 100644
106
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
113
--- a/block/mirror.c
107
BlockDriverState *bs;
114
+++ b/block/mirror.c
108
- char *full_backing = g_new0(char, PATH_MAX);
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
109
+ char *full_backing;
116
110
int back_flags;
117
if (s->bdev_length > base_length) {
111
QDict *backing_options = NULL;
118
ret = blk_truncate(s->target, s->bdev_length, false,
112
119
- PREALLOC_MODE_OFF, NULL);
113
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
120
+ PREALLOC_MODE_OFF, 0, NULL);
114
- full_backing, PATH_MAX,
121
if (ret < 0) {
115
- &local_err);
122
goto immediate_exit;
116
+ full_backing =
123
}
117
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
124
diff --git a/block/qcow2.c b/block/qcow2.c
118
+ &local_err);
125
index XXXXXXX..XXXXXXX 100644
119
if (local_err) {
126
--- a/block/qcow2.c
120
- g_free(full_backing);
127
+++ b/block/qcow2.c
121
goto out;
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
122
}
129
123
+ assert(full_backing);
130
/* Okay, now that we have a valid image, let's give it the right size */
124
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
125
/* backing files always opened read-only */
132
- errp);
126
back_flags = flags;
133
+ 0, errp);
134
if (ret < 0) {
135
error_prepend(errp, "Could not resize image: ");
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
127
diff --git a/block/vmdk.c b/block/vmdk.c
192
diff --git a/block/vmdk.c b/block/vmdk.c
128
index XXXXXXX..XXXXXXX 100644
193
index XXXXXXX..XXXXXXX 100644
129
--- a/block/vmdk.c
194
--- a/block/vmdk.c
130
+++ b/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
132
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
133
if (backing_file) {
216
* for description file */
134
BlockBackend *backing;
217
if (desc_offset == 0) {
135
- char *full_backing = g_new0(char, PATH_MAX);
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
136
- bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
137
- full_backing, PATH_MAX,
220
if (ret < 0) {
138
- &local_err);
221
goto exit;
139
+ char *full_backing =
222
}
140
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename,
223
diff --git a/block/vpc.c b/block/vpc.c
141
+ backing_file,
224
index XXXXXXX..XXXXXXX 100644
142
+ &local_err);
225
--- a/block/vpc.c
143
if (local_err) {
226
+++ b/block/vpc.c
144
- g_free(full_backing);
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
145
error_propagate(errp, local_err);
228
/* Add footer to total size */
146
ret = -ENOENT;
229
total_size += HEADER_SIZE;
147
goto exit;
230
148
}
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
149
+ assert(full_backing);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
150
233
if (ret < 0) {
151
backing = blk_new_open(full_backing, NULL, NULL,
234
return ret;
152
BDRV_O_NO_BACKING, errp);
235
}
236
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
239
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
241
}
242
243
bdrv_drained_begin(bs);
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
246
bdrv_drained_end(bs);
247
248
out:
153
diff --git a/qemu-img.c b/qemu-img.c
249
diff --git a/qemu-img.c b/qemu-img.c
154
index XXXXXXX..XXXXXXX 100644
250
index XXXXXXX..XXXXXXX 100644
155
--- a/qemu-img.c
251
--- a/qemu-img.c
156
+++ b/qemu-img.c
252
+++ b/qemu-img.c
157
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
158
bdrv_refresh_filename(bs);
254
* resizing, so pass @exact=true. It is of no use to report
159
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
255
* success when the image has not actually been resized.
160
: bs->filename;
256
*/
161
- out_real_path = g_malloc(PATH_MAX);
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
162
-
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
163
- bdrv_get_full_backing_filename_from_filename(overlay_filename,
259
if (!ret) {
164
- out_baseimg,
260
qprintf(quiet, "Image resized.\n");
165
- out_real_path,
261
} else {
166
- PATH_MAX,
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
167
- &local_err);
263
index XXXXXXX..XXXXXXX 100644
168
+ out_real_path =
264
--- a/qemu-io-cmds.c
169
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
265
+++ b/qemu-io-cmds.c
170
+ out_baseimg,
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
171
+ &local_err);
267
* exact=true. It is better to err on the "emit more errors" side
172
if (local_err) {
268
* than to be overly permissive.
173
error_reportf_err(local_err,
269
*/
174
"Could not resolve backing filename: ");
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
175
ret = -1;
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
176
- g_free(out_real_path);
272
if (ret < 0) {
177
goto out;
273
error_report_err(local_err);
178
}
274
return ret;
179
180
--
275
--
181
2.20.1
276
2.25.3
182
277
183
278
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
2
6
3
L1 table entries have a field to store the offset of an L2 table.
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
The rest of the bits of the entry are currently reserved except from
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
5
bit 63, which stores the COPIED flag.
6
7
The offset is always taken from the entry using L1E_OFFSET_MASK to
8
ensure that we only use the bits that belong to that field.
9
10
While that mask is used every time we read from the L1 table, it is
11
never used when we write to it. Due to the limits set elsewhere in the
12
code QEMU can never produce L2 table offsets that don't fit in that
13
field so any such offset when allocating an L2 table would indicate a
14
bug in QEMU.
15
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
12
---
20
block/qcow2-cluster.c | 3 +++
13
block/qcow2-cluster.c | 2 +-
21
1 file changed, 3 insertions(+)
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
15
2 files changed, 35 insertions(+), 1 deletion(-)
22
16
23
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2-cluster.c
19
--- a/block/qcow2-cluster.c
26
+++ b/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
27
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
28
goto fail;
22
/* Caller must pass aligned values, except at image end */
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
27
28
/* The zero flag is only supported by version 3 and newer */
29
if (s->qcow_version < 3) {
30
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
29
}
44
}
30
45
31
+ /* The offset must fit in the offset field of the L1 table entry */
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
32
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
33
+
48
+
34
/* If we're allocating the table at offset 0 then something is wrong */
49
+ /*
35
if (l2_offset == 0) {
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
36
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
52
+ * at the end of the image (which it is here).
53
+ */
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
55
+ if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
57
+ goto fail;
58
+ }
59
+
60
+ /* Write explicit zeros for the unaligned head */
61
+ if (zero_start > old_length) {
62
+ uint64_t len = zero_start - old_length;
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
64
+ QEMUIOVector qiov;
65
+ qemu_iovec_init_buf(&qiov, buf, len);
66
+
67
+ qemu_co_mutex_unlock(&s->lock);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
69
+ qemu_co_mutex_lock(&s->lock);
70
+
71
+ qemu_vfree(buf);
72
+ if (ret < 0) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
37
--
82
--
38
2.20.1
83
2.25.3
39
84
40
85
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
The raw format driver can simply forward the flag and let its bs->file
2
child take care of actually providing the zeros.
2
3
3
This new field can be set by block drivers to list the runtime options
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
they accept that may influence the contents of the respective BDS. As of
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
a follow-up patch, this list will be used by the common
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
bdrv_refresh_filename() implementation to decide which options to put
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
into BDS.full_open_options (and consequently whether a JSON filename has
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
8
to be created), thus freeing the drivers of having to implement that
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
logic themselves.
10
---
11
block/raw-format.c | 4 +++-
12
1 file changed, 3 insertions(+), 1 deletion(-)
10
13
11
Additionally, this patch adds the field to all of the block drivers that
12
need it and sets it accordingly.
13
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Message-id: 20190201192935.18394-22-mreitz@redhat.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
include/block/block_int.h | 7 +++++++
20
block/blkdebug.c | 16 ++++++++++++++++
21
block/blklogwrites.c | 8 ++++++++
22
block/crypto.c | 8 ++++++++
23
block/curl.c | 21 +++++++++++++++++++++
24
block/gluster.c | 19 +++++++++++++++++++
25
block/iscsi.c | 18 ++++++++++++++++++
26
block/nbd.c | 14 ++++++++++++++
27
block/nfs.c | 11 +++++++++++
28
block/null.c | 9 +++++++++
29
block/nvme.c | 8 ++++++++
30
block/qcow.c | 7 +++++++
31
block/qcow2.c | 7 +++++++
32
block/quorum.c | 11 +++++++++++
33
block/raw-format.c | 10 +++++++++-
34
block/rbd.c | 14 ++++++++++++++
35
block/replication.c | 8 ++++++++
36
block/sheepdog.c | 12 ++++++++++++
37
block/ssh.c | 12 ++++++++++++
38
block/throttle.c | 7 +++++++
39
block/vpc.c | 7 +++++++
40
block/vvfat.c | 12 ++++++++++++
41
block/vxhs.c | 11 +++++++++++
42
23 files changed, 256 insertions(+), 1 deletion(-)
43
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
50
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
51
QLIST_ENTRY(BlockDriver) list;
52
+
53
+ /* Pointer to a NULL-terminated array of names of strong options
54
+ * that can be specified for bdrv_open(). A strong option is one
55
+ * that changes the data of a BDS.
56
+ * If this pointer is NULL, the array is considered empty.
57
+ * "filename" and "driver" are always considered strong. */
58
+ const char *const *strong_runtime_opts;
59
};
60
61
typedef struct BlockLimits {
62
diff --git a/block/blkdebug.c b/block/blkdebug.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/blkdebug.c
65
+++ b/block/blkdebug.c
66
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
67
return 0;
68
}
69
70
+static const char *const blkdebug_strong_runtime_opts[] = {
71
+ "config",
72
+ "inject-error.",
73
+ "set-state.",
74
+ "align",
75
+ "max-transfer",
76
+ "opt-write-zero",
77
+ "max-write-zero",
78
+ "opt-discard",
79
+ "max-discard",
80
+
81
+ NULL
82
+};
83
+
84
static BlockDriver bdrv_blkdebug = {
85
.format_name = "blkdebug",
86
.protocol_name = "blkdebug",
87
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
88
= blkdebug_debug_remove_breakpoint,
89
.bdrv_debug_resume = blkdebug_debug_resume,
90
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
91
+
92
+ .strong_runtime_opts = blkdebug_strong_runtime_opts,
93
};
94
95
static void bdrv_blkdebug_init(void)
96
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blklogwrites.c
99
+++ b/block/blklogwrites.c
100
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
101
LOG_DISCARD_FLAG, false);
102
}
103
104
+static const char *const blk_log_writes_strong_runtime_opts[] = {
105
+ "log-append",
106
+ "log-sector-size",
107
+
108
+ NULL
109
+};
110
+
111
static BlockDriver bdrv_blk_log_writes = {
112
.format_name = "blklogwrites",
113
.instance_size = sizeof(BDRVBlkLogWritesState),
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
115
.bdrv_co_block_status = bdrv_co_block_status_from_file,
116
117
.is_filter = true,
118
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
119
};
120
121
static void bdrv_blk_log_writes_init(void)
122
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
125
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
127
return spec_info;
128
}
129
130
+static const char *const block_crypto_strong_runtime_opts[] = {
131
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
132
+
133
+ NULL
134
+};
135
+
136
BlockDriver bdrv_crypto_luks = {
137
.format_name = "luks",
138
.instance_size = sizeof(BlockCrypto),
139
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
140
.bdrv_getlength = block_crypto_getlength,
141
.bdrv_get_info = block_crypto_get_info_luks,
142
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
143
+
144
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
145
};
146
147
static void block_crypto_init(void)
148
diff --git a/block/curl.c b/block/curl.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/curl.c
151
+++ b/block/curl.c
152
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
153
return s->len;
154
}
155
156
+static const char *const curl_strong_runtime_opts[] = {
157
+ CURL_BLOCK_OPT_URL,
158
+ CURL_BLOCK_OPT_SSLVERIFY,
159
+ CURL_BLOCK_OPT_COOKIE,
160
+ CURL_BLOCK_OPT_COOKIE_SECRET,
161
+ CURL_BLOCK_OPT_USERNAME,
162
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
163
+ CURL_BLOCK_OPT_PROXY_USERNAME,
164
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
165
+
166
+ NULL
167
+};
168
+
169
static BlockDriver bdrv_http = {
170
.format_name = "http",
171
.protocol_name = "http",
172
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
173
174
.bdrv_detach_aio_context = curl_detach_aio_context,
175
.bdrv_attach_aio_context = curl_attach_aio_context,
176
+
177
+ .strong_runtime_opts = curl_strong_runtime_opts,
178
};
179
180
static BlockDriver bdrv_https = {
181
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
182
183
.bdrv_detach_aio_context = curl_detach_aio_context,
184
.bdrv_attach_aio_context = curl_attach_aio_context,
185
+
186
+ .strong_runtime_opts = curl_strong_runtime_opts,
187
};
188
189
static BlockDriver bdrv_ftp = {
190
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
191
192
.bdrv_detach_aio_context = curl_detach_aio_context,
193
.bdrv_attach_aio_context = curl_attach_aio_context,
194
+
195
+ .strong_runtime_opts = curl_strong_runtime_opts,
196
};
197
198
static BlockDriver bdrv_ftps = {
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
200
201
.bdrv_detach_aio_context = curl_detach_aio_context,
202
.bdrv_attach_aio_context = curl_attach_aio_context,
203
+
204
+ .strong_runtime_opts = curl_strong_runtime_opts,
205
};
206
207
static void curl_block_init(void)
208
diff --git a/block/gluster.c b/block/gluster.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/gluster.c
211
+++ b/block/gluster.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
213
}
214
215
216
+static const char *const gluster_strong_open_opts[] = {
217
+ GLUSTER_OPT_VOLUME,
218
+ GLUSTER_OPT_PATH,
219
+ GLUSTER_OPT_TYPE,
220
+ GLUSTER_OPT_SERVER_PATTERN,
221
+ GLUSTER_OPT_HOST,
222
+ GLUSTER_OPT_PORT,
223
+ GLUSTER_OPT_TO,
224
+ GLUSTER_OPT_IPV4,
225
+ GLUSTER_OPT_IPV6,
226
+ GLUSTER_OPT_SOCKET,
227
+
228
+ NULL
229
+};
230
+
231
static BlockDriver bdrv_gluster = {
232
.format_name = "gluster",
233
.protocol_name = "gluster",
234
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
235
#endif
236
.bdrv_co_block_status = qemu_gluster_co_block_status,
237
.create_opts = &qemu_gluster_create_opts,
238
+ .strong_runtime_opts = gluster_strong_open_opts,
239
};
240
241
static BlockDriver bdrv_gluster_tcp = {
242
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
243
#endif
244
.bdrv_co_block_status = qemu_gluster_co_block_status,
245
.create_opts = &qemu_gluster_create_opts,
246
+ .strong_runtime_opts = gluster_strong_open_opts,
247
};
248
249
static BlockDriver bdrv_gluster_unix = {
250
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
251
#endif
252
.bdrv_co_block_status = qemu_gluster_co_block_status,
253
.create_opts = &qemu_gluster_create_opts,
254
+ .strong_runtime_opts = gluster_strong_open_opts,
255
};
256
257
/* rdma is deprecated (actually never supported for volfile fetch).
258
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
259
#endif
260
.bdrv_co_block_status = qemu_gluster_co_block_status,
261
.create_opts = &qemu_gluster_create_opts,
262
+ .strong_runtime_opts = gluster_strong_open_opts,
263
};
264
265
static void bdrv_gluster_init(void)
266
diff --git a/block/iscsi.c b/block/iscsi.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/block/iscsi.c
269
+++ b/block/iscsi.c
270
@@ -XXX,XX +XXX,XX @@ static QemuOptsList iscsi_create_opts = {
271
}
272
};
273
274
+static const char *const iscsi_strong_runtime_opts[] = {
275
+ "transport",
276
+ "portal",
277
+ "target",
278
+ "user",
279
+ "password",
280
+ "password-secret",
281
+ "lun",
282
+ "initiator-name",
283
+ "header-digest",
284
+
285
+ NULL
286
+};
287
+
288
static BlockDriver bdrv_iscsi = {
289
.format_name = "iscsi",
290
.protocol_name = "iscsi",
291
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
292
293
.bdrv_detach_aio_context = iscsi_detach_aio_context,
294
.bdrv_attach_aio_context = iscsi_attach_aio_context,
295
+
296
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
297
};
298
299
#if LIBISCSI_API_VERSION >= (20160603)
300
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
301
302
.bdrv_detach_aio_context = iscsi_detach_aio_context,
303
.bdrv_attach_aio_context = iscsi_attach_aio_context,
304
+
305
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
306
};
307
#endif
308
309
diff --git a/block/nbd.c b/block/nbd.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/block/nbd.c
312
+++ b/block/nbd.c
313
@@ -XXX,XX +XXX,XX @@ static char *nbd_dirname(BlockDriverState *bs, Error **errp)
314
return NULL;
315
}
316
317
+static const char *const nbd_strong_runtime_opts[] = {
318
+ "path",
319
+ "host",
320
+ "port",
321
+ "export",
322
+ "tls-creds",
323
+ "server.",
324
+
325
+ NULL
326
+};
327
+
328
static BlockDriver bdrv_nbd = {
329
.format_name = "nbd",
330
.protocol_name = "nbd",
331
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
332
.bdrv_refresh_filename = nbd_refresh_filename,
333
.bdrv_co_block_status = nbd_client_co_block_status,
334
.bdrv_dirname = nbd_dirname,
335
+ .strong_runtime_opts = nbd_strong_runtime_opts,
336
};
337
338
static BlockDriver bdrv_nbd_tcp = {
339
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
340
.bdrv_refresh_filename = nbd_refresh_filename,
341
.bdrv_co_block_status = nbd_client_co_block_status,
342
.bdrv_dirname = nbd_dirname,
343
+ .strong_runtime_opts = nbd_strong_runtime_opts,
344
};
345
346
static BlockDriver bdrv_nbd_unix = {
347
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
348
.bdrv_refresh_filename = nbd_refresh_filename,
349
.bdrv_co_block_status = nbd_client_co_block_status,
350
.bdrv_dirname = nbd_dirname,
351
+ .strong_runtime_opts = nbd_strong_runtime_opts,
352
};
353
354
static void bdrv_nbd_init(void)
355
diff --git a/block/nfs.c b/block/nfs.c
356
index XXXXXXX..XXXXXXX 100644
357
--- a/block/nfs.c
358
+++ b/block/nfs.c
359
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
360
}
361
#endif
362
363
+static const char *nfs_strong_runtime_opts[] = {
364
+ "path",
365
+ "user",
366
+ "group",
367
+ "server.",
368
+
369
+ NULL
370
+};
371
+
372
static BlockDriver bdrv_nfs = {
373
.format_name = "nfs",
374
.protocol_name = "nfs",
375
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
376
.bdrv_refresh_filename = nfs_refresh_filename,
377
.bdrv_dirname = nfs_dirname,
378
379
+ .strong_runtime_opts = nfs_strong_runtime_opts,
380
+
381
#ifdef LIBNFS_FEATURE_PAGECACHE
382
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
383
#endif
384
diff --git a/block/null.c b/block/null.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/block/null.c
387
+++ b/block/null.c
388
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
389
bs->full_open_options = qobject_ref(opts);
390
}
391
392
+static const char *const null_strong_runtime_opts[] = {
393
+ BLOCK_OPT_SIZE,
394
+ NULL_OPT_ZEROES,
395
+
396
+ NULL
397
+};
398
+
399
static BlockDriver bdrv_null_co = {
400
.format_name = "null-co",
401
.protocol_name = "null-co",
402
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
403
.bdrv_co_block_status = null_co_block_status,
404
405
.bdrv_refresh_filename = null_refresh_filename,
406
+ .strong_runtime_opts = null_strong_runtime_opts,
407
};
408
409
static BlockDriver bdrv_null_aio = {
410
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
411
.bdrv_co_block_status = null_co_block_status,
412
413
.bdrv_refresh_filename = null_refresh_filename,
414
+ .strong_runtime_opts = null_strong_runtime_opts,
415
};
416
417
static void bdrv_null_init(void)
418
diff --git a/block/nvme.c b/block/nvme.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/nvme.c
421
+++ b/block/nvme.c
422
@@ -XXX,XX +XXX,XX @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host)
423
qemu_vfio_dma_unmap(s->vfio, host);
424
}
425
426
+static const char *const nvme_strong_runtime_opts[] = {
427
+ NVME_BLOCK_OPT_DEVICE,
428
+ NVME_BLOCK_OPT_NAMESPACE,
429
+
430
+ NULL
431
+};
432
+
433
static BlockDriver bdrv_nvme = {
434
.format_name = "nvme",
435
.protocol_name = "nvme",
436
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
437
438
.bdrv_refresh_filename = nvme_refresh_filename,
439
.bdrv_refresh_limits = nvme_refresh_limits,
440
+ .strong_runtime_opts = nvme_strong_runtime_opts,
441
442
.bdrv_detach_aio_context = nvme_detach_aio_context,
443
.bdrv_attach_aio_context = nvme_attach_aio_context,
444
diff --git a/block/qcow.c b/block/qcow.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/block/qcow.c
447
+++ b/block/qcow.c
448
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
449
}
450
};
451
452
+static const char *const qcow_strong_runtime_opts[] = {
453
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
454
+
455
+ NULL
456
+};
457
+
458
static BlockDriver bdrv_qcow = {
459
.format_name    = "qcow",
460
.instance_size    = sizeof(BDRVQcowState),
461
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
462
.bdrv_get_info = qcow_get_info,
463
464
.create_opts = &qcow_create_opts,
465
+ .strong_runtime_opts = qcow_strong_runtime_opts,
466
};
467
468
static void bdrv_qcow_init(void)
469
diff --git a/block/qcow2.c b/block/qcow2.c
470
index XXXXXXX..XXXXXXX 100644
471
--- a/block/qcow2.c
472
+++ b/block/qcow2.c
473
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
474
}
475
};
476
477
+static const char *const qcow2_strong_runtime_opts[] = {
478
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
479
+
480
+ NULL
481
+};
482
+
483
BlockDriver bdrv_qcow2 = {
484
.format_name = "qcow2",
485
.instance_size = sizeof(BDRVQcow2State),
486
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
487
.bdrv_inactivate = qcow2_inactivate,
488
489
.create_opts = &qcow2_create_opts,
490
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
491
.bdrv_co_check = qcow2_co_check,
492
.bdrv_amend_options = qcow2_amend_options,
493
494
diff --git a/block/quorum.c b/block/quorum.c
495
index XXXXXXX..XXXXXXX 100644
496
--- a/block/quorum.c
497
+++ b/block/quorum.c
498
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
499
return NULL;
500
}
501
502
+static const char *const quorum_strong_runtime_opts[] = {
503
+ QUORUM_OPT_VOTE_THRESHOLD,
504
+ QUORUM_OPT_BLKVERIFY,
505
+ QUORUM_OPT_REWRITE,
506
+ QUORUM_OPT_READ_PATTERN,
507
+
508
+ NULL
509
+};
510
+
511
static BlockDriver bdrv_quorum = {
512
.format_name = "quorum",
513
514
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
515
516
.is_filter = true,
517
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
518
+
519
+ .strong_runtime_opts = quorum_strong_runtime_opts,
520
};
521
522
static void bdrv_quorum_init(void)
523
diff --git a/block/raw-format.c b/block/raw-format.c
14
diff --git a/block/raw-format.c b/block/raw-format.c
524
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
525
--- a/block/raw-format.c
16
--- a/block/raw-format.c
526
+++ b/block/raw-format.c
17
+++ b/block/raw-format.c
527
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
528
read_flags, write_flags);
19
20
s->size = offset;
21
offset += s->offset;
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
529
}
24
}
530
25
531
+static const char *const raw_strong_runtime_opts[] = {
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
532
+ "offset",
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
533
+ "size",
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
534
+
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
535
+ NULL
30
bs->file->bs->supported_zero_flags);
536
+};
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
537
+
32
+ BDRV_REQ_ZERO_WRITE;
538
BlockDriver bdrv_raw = {
33
539
.format_name = "raw",
34
if (bs->probed && !bdrv_is_read_only(bs)) {
540
.instance_size = sizeof(BDRVRawState),
35
bdrv_refresh_filename(bs->file->bs);
541
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
542
.bdrv_lock_medium = &raw_lock_medium,
543
.bdrv_co_ioctl = &raw_co_ioctl,
544
.create_opts = &raw_create_opts,
545
- .bdrv_has_zero_init = &raw_has_zero_init
546
+ .bdrv_has_zero_init = &raw_has_zero_init,
547
+ .strong_runtime_opts = raw_strong_runtime_opts,
548
};
549
550
static void bdrv_raw_init(void)
551
diff --git a/block/rbd.c b/block/rbd.c
552
index XXXXXXX..XXXXXXX 100644
553
--- a/block/rbd.c
554
+++ b/block/rbd.c
555
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_rbd_create_opts = {
556
}
557
};
558
559
+static const char *const qemu_rbd_strong_runtime_opts[] = {
560
+ "pool",
561
+ "image",
562
+ "conf",
563
+ "snapshot",
564
+ "user",
565
+ "server.",
566
+ "password-secret",
567
+
568
+ NULL
569
+};
570
+
571
static BlockDriver bdrv_rbd = {
572
.format_name = "rbd",
573
.instance_size = sizeof(BDRVRBDState),
574
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
575
#ifdef LIBRBD_SUPPORTS_INVALIDATE
576
.bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache,
577
#endif
578
+
579
+ .strong_runtime_opts = qemu_rbd_strong_runtime_opts,
580
};
581
582
static void bdrv_rbd_init(void)
583
diff --git a/block/replication.c b/block/replication.c
584
index XXXXXXX..XXXXXXX 100644
585
--- a/block/replication.c
586
+++ b/block/replication.c
587
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
588
aio_context_release(aio_context);
589
}
590
591
+static const char *const replication_strong_runtime_opts[] = {
592
+ REPLICATION_MODE,
593
+ REPLICATION_TOP_ID,
594
+
595
+ NULL
596
+};
597
+
598
BlockDriver bdrv_replication = {
599
.format_name = "replication",
600
.instance_size = sizeof(BDRVReplicationState),
601
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_replication = {
602
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
603
604
.has_variable_length = true,
605
+ .strong_runtime_opts = replication_strong_runtime_opts,
606
};
607
608
static void bdrv_replication_init(void)
609
diff --git a/block/sheepdog.c b/block/sheepdog.c
610
index XXXXXXX..XXXXXXX 100644
611
--- a/block/sheepdog.c
612
+++ b/block/sheepdog.c
613
@@ -XXX,XX +XXX,XX @@ static QemuOptsList sd_create_opts = {
614
}
615
};
616
617
+static const char *const sd_strong_runtime_opts[] = {
618
+ "vdi",
619
+ "snap-id",
620
+ "tag",
621
+ "server.",
622
+
623
+ NULL
624
+};
625
+
626
static BlockDriver bdrv_sheepdog = {
627
.format_name = "sheepdog",
628
.protocol_name = "sheepdog",
629
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
630
.bdrv_attach_aio_context = sd_attach_aio_context,
631
632
.create_opts = &sd_create_opts,
633
+ .strong_runtime_opts = sd_strong_runtime_opts,
634
};
635
636
static BlockDriver bdrv_sheepdog_tcp = {
637
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
638
.bdrv_attach_aio_context = sd_attach_aio_context,
639
640
.create_opts = &sd_create_opts,
641
+ .strong_runtime_opts = sd_strong_runtime_opts,
642
};
643
644
static BlockDriver bdrv_sheepdog_unix = {
645
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
646
.bdrv_attach_aio_context = sd_attach_aio_context,
647
648
.create_opts = &sd_create_opts,
649
+ .strong_runtime_opts = sd_strong_runtime_opts,
650
};
651
652
static void bdrv_sheepdog_init(void)
653
diff --git a/block/ssh.c b/block/ssh.c
654
index XXXXXXX..XXXXXXX 100644
655
--- a/block/ssh.c
656
+++ b/block/ssh.c
657
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
658
return ssh_grow_file(s, offset, errp);
659
}
660
661
+static const char *const ssh_strong_runtime_opts[] = {
662
+ "host",
663
+ "port",
664
+ "path",
665
+ "user",
666
+ "host_key_check",
667
+ "server.",
668
+
669
+ NULL
670
+};
671
+
672
static BlockDriver bdrv_ssh = {
673
.format_name = "ssh",
674
.protocol_name = "ssh",
675
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
676
.bdrv_co_truncate = ssh_co_truncate,
677
.bdrv_co_flush_to_disk = ssh_co_flush,
678
.create_opts = &ssh_create_opts,
679
+ .strong_runtime_opts = ssh_strong_runtime_opts,
680
};
681
682
static void bdrv_ssh_init(void)
683
diff --git a/block/throttle.c b/block/throttle.c
684
index XXXXXXX..XXXXXXX 100644
685
--- a/block/throttle.c
686
+++ b/block/throttle.c
687
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs)
688
atomic_dec(&tgm->io_limits_disabled);
689
}
690
691
+static const char *const throttle_strong_runtime_opts[] = {
692
+ QEMU_OPT_THROTTLE_GROUP_NAME,
693
+
694
+ NULL
695
+};
696
+
697
static BlockDriver bdrv_throttle = {
698
.format_name = "throttle",
699
.instance_size = sizeof(ThrottleGroupMember),
700
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
701
.bdrv_co_drain_end = throttle_co_drain_end,
702
703
.is_filter = true,
704
+ .strong_runtime_opts = throttle_strong_runtime_opts,
705
};
706
707
static void bdrv_throttle_init(void)
708
diff --git a/block/vpc.c b/block/vpc.c
709
index XXXXXXX..XXXXXXX 100644
710
--- a/block/vpc.c
711
+++ b/block/vpc.c
712
@@ -XXX,XX +XXX,XX @@ static QemuOptsList vpc_create_opts = {
713
}
714
};
715
716
+static const char *const vpc_strong_runtime_opts[] = {
717
+ VPC_OPT_SIZE_CALC,
718
+
719
+ NULL
720
+};
721
+
722
static BlockDriver bdrv_vpc = {
723
.format_name = "vpc",
724
.instance_size = sizeof(BDRVVPCState),
725
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
726
727
.create_opts = &vpc_create_opts,
728
.bdrv_has_zero_init = vpc_has_zero_init,
729
+ .strong_runtime_opts = vpc_strong_runtime_opts,
730
};
731
732
static void bdrv_vpc_init(void)
733
diff --git a/block/vvfat.c b/block/vvfat.c
734
index XXXXXXX..XXXXXXX 100644
735
--- a/block/vvfat.c
736
+++ b/block/vvfat.c
737
@@ -XXX,XX +XXX,XX @@ static void vvfat_close(BlockDriverState *bs)
738
}
739
}
740
741
+static const char *const vvfat_strong_runtime_opts[] = {
742
+ "dir",
743
+ "fat-type",
744
+ "floppy",
745
+ "label",
746
+ "rw",
747
+
748
+ NULL
749
+};
750
+
751
static BlockDriver bdrv_vvfat = {
752
.format_name = "vvfat",
753
.protocol_name = "fat",
754
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
755
.bdrv_co_preadv = vvfat_co_preadv,
756
.bdrv_co_pwritev = vvfat_co_pwritev,
757
.bdrv_co_block_status = vvfat_co_block_status,
758
+
759
+ .strong_runtime_opts = vvfat_strong_runtime_opts,
760
};
761
762
static void bdrv_vvfat_init(void)
763
diff --git a/block/vxhs.c b/block/vxhs.c
764
index XXXXXXX..XXXXXXX 100644
765
--- a/block/vxhs.c
766
+++ b/block/vxhs.c
767
@@ -XXX,XX +XXX,XX @@ static int64_t vxhs_getlength(BlockDriverState *bs)
768
return vdisk_size;
769
}
770
771
+static const char *const vxhs_strong_runtime_opts[] = {
772
+ VXHS_OPT_VDISK_ID,
773
+ "tls-creds",
774
+ VXHS_OPT_HOST,
775
+ VXHS_OPT_PORT,
776
+ VXHS_OPT_SERVER".",
777
+
778
+ NULL
779
+};
780
+
781
static BlockDriver bdrv_vxhs = {
782
.format_name = "vxhs",
783
.protocol_name = "vxhs",
784
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vxhs = {
785
.bdrv_getlength = vxhs_getlength,
786
.bdrv_aio_preadv = vxhs_aio_preadv,
787
.bdrv_aio_pwritev = vxhs_aio_pwritev,
788
+ .strong_runtime_opts = vxhs_strong_runtime_opts,
789
};
790
791
static void bdrv_vxhs_init(void)
792
--
36
--
793
2.20.1
37
2.25.3
794
38
795
39
diff view generated by jsdifflib
1
virtio_blk_dma_restart_bh() submits new requests, so in order to make
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
2
sure that these requests are not started inside a drained section of the
2
OS, so we can advertise the flag and just ignore it.
3
attached BlockBackend, we need to make sure that draining the
4
BlockBackend waits for the BH to be executed.
5
6
This BH is still questionable because its scheduled in the main thread
7
instead of the configured iothread. Leave a FIXME comment for this.
8
9
But with this fix, enabling the data plane at least waits for these
10
requests (in bdrv_set_aio_context()) instead of changing the AioContext
11
under their feet and making them run in the wrong thread, causing
12
crashes and failures (e.g. due to missing locking).
13
3
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
10
---
16
hw/block/virtio-blk.c | 4 ++++
11
block/file-posix.c | 4 ++++
17
1 file changed, 4 insertions(+)
12
1 file changed, 4 insertions(+)
18
13
19
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
14
diff --git a/block/file-posix.c b/block/file-posix.c
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/block/virtio-blk.c
16
--- a/block/file-posix.c
22
+++ b/hw/block/virtio-blk.c
17
+++ b/block/file-posix.c
23
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
24
if (mrb.num_reqs) {
19
#endif
25
virtio_blk_submit_multireq(s->blk, &mrb);
20
26
}
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
27
+ blk_dec_in_flight(s->conf.conf.blk);
22
+ if (S_ISREG(st.st_mode)) {
28
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
23
+ /* When extending regular files, we get zeros from the OS */
29
}
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
30
25
+ }
31
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
26
ret = 0;
32
}
27
fail:
33
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
34
if (!s->bh) {
35
+ /* FIXME The data plane is not started yet, so these requests are
36
+ * processed in the main thread. */
37
s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
38
virtio_blk_dma_restart_bh, s);
39
+ blk_inc_in_flight(s->conf.conf.blk);
40
qemu_bh_schedule(s->bh);
41
}
42
}
43
--
29
--
44
2.20.1
30
2.25.3
45
31
46
32
diff view generated by jsdifflib
Deleted patch
1
nbd_client_attach_aio_context() schedules connection_co in the new
2
AioContext and this way reenters it in any arbitrary place that has
3
yielded. We can restrict this a bit to the function call where the
4
coroutine actually sits waiting when it's idle.
5
1
6
This doesn't solve any bug yet, but it shows where in the code we need
7
to support this random reentrance and where we don't have to care.
8
9
Add FIXME comments for the existing bugs that the rest of this series
10
will fix.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
15
block/nbd-client.h | 1 +
16
block/nbd-client.c | 22 ++++++++++++++++++++++
17
2 files changed, 23 insertions(+)
18
19
diff --git a/block/nbd-client.h b/block/nbd-client.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/nbd-client.h
22
+++ b/block/nbd-client.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct NBDClientSession {
24
25
NBDClientRequest requests[MAX_NBD_REQUESTS];
26
NBDReply reply;
27
+ BlockDriverState *bs;
28
bool quit;
29
} NBDClientSession;
30
31
diff --git a/block/nbd-client.c b/block/nbd-client.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/nbd-client.c
34
+++ b/block/nbd-client.c
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
36
Error *local_err = NULL;
37
38
while (!s->quit) {
39
+ /*
40
+ * The NBD client can only really be considered idle when it has
41
+ * yielded from qio_channel_readv_all_eof(), waiting for data. This is
42
+ * the point where the additional scheduled coroutine entry happens
43
+ * after nbd_client_attach_aio_context().
44
+ *
45
+ * Therefore we keep an additional in_flight reference all the time and
46
+ * only drop it temporarily here.
47
+ *
48
+ * FIXME This is not safe because the QIOChannel could wake up the
49
+ * coroutine for a second time; it is not prepared for coroutine
50
+ * resumption from external code.
51
+ */
52
+ bdrv_dec_in_flight(s->bs);
53
assert(s->reply.handle == 0);
54
ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
55
+ bdrv_inc_in_flight(s->bs);
56
+
57
if (local_err) {
58
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
59
error_free(local_err);
60
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
61
62
s->quit = true;
63
nbd_recv_coroutines_wake_all(s);
64
+ bdrv_dec_in_flight(s->bs);
65
+
66
s->connection_co = NULL;
67
aio_wait_kick();
68
}
69
@@ -XXX,XX +XXX,XX @@ void nbd_client_attach_aio_context(BlockDriverState *bs,
70
{
71
NBDClientSession *client = nbd_get_client_session(bs);
72
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
73
+
74
+ /* FIXME Really need a bdrv_inc_in_flight() here */
75
aio_co_schedule(new_context, client->connection_co);
76
}
77
78
@@ -XXX,XX +XXX,XX @@ static int nbd_client_connect(BlockDriverState *bs,
79
* kick the reply mechanism. */
80
qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);
81
client->connection_co = qemu_coroutine_create(nbd_connection_entry, client);
82
+ bdrv_inc_in_flight(bs);
83
nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));
84
85
logout("Established connection with NBD server\n");
86
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
87
{
88
NBDClientSession *client = nbd_get_client_session(bs);
89
90
+ client->bs = bs;
91
qemu_co_mutex_init(&client->send_mutex);
92
qemu_co_queue_init(&client->free_sema);
93
94
--
95
2.20.1
96
97
diff view generated by jsdifflib
1
When a drained node changes its AioContext, we need to move its
1
When extending the size of an image that has a backing file larger than
2
aio_disable_external() to the new context, too.
2
its old size, make sure that the backing file data doesn't become
3
visible in the guest, but the added area is properly zeroed out.
3
4
4
Without this fix, drain_end will try to reenable the new context, which
5
Consider the following scenario where the overlay is shorter than its
5
has never been disabled, so an assertion failure is triggered.
6
backing file:
7
8
base.qcow2: AAAAAAAA
9
overlay.qcow2: BBBB
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
6
29
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
35
---
10
block.c | 7 +++++++
36
block/io.c | 25 +++++++++++++++++++++++++
11
1 file changed, 7 insertions(+)
37
1 file changed, 25 insertions(+)
12
38
13
diff --git a/block.c b/block.c
39
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
41
--- a/block/io.c
16
+++ b/block.c
42
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ void bdrv_detach_aio_context(BlockDriverState *bs)
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
18
bdrv_detach_aio_context(child->bs);
44
goto out;
19
}
45
}
20
46
21
+ if (bs->quiesce_counter) {
47
+ /*
22
+ aio_enable_external(bs->aio_context);
48
+ * If the image has a backing file that is large enough that it would
23
+ }
49
+ * provide data for the new area, we cannot leave it unallocated because
24
bs->aio_context = NULL;
50
+ * then the backing file content would become visible. Instead, zero-fill
25
}
51
+ * the new area.
26
52
+ *
27
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
53
+ * Note that if the image has a backing file, but was opened without the
28
return;
54
+ * backing file, taking care of keeping things consistent with that backing
29
}
55
+ * file is the user's responsibility.
30
56
+ */
31
+ if (bs->quiesce_counter) {
57
+ if (new_bytes && bs->backing) {
32
+ aio_disable_external(new_context);
58
+ int64_t backing_len;
59
+
60
+ backing_len = bdrv_getlength(backing_bs(bs));
61
+ if (backing_len < 0) {
62
+ ret = backing_len;
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
64
+ goto out;
65
+ }
66
+
67
+ if (backing_len > old_size) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
69
+ }
33
+ }
70
+ }
34
+
71
+
35
bs->aio_context = new_context;
72
if (drv->bdrv_co_truncate) {
36
73
if (flags & ~bs->supported_truncate_flags) {
37
QLIST_FOREACH(child, &bs->children, next) {
74
error_setg(errp, "Block driver does not support requested flags");
38
--
75
--
39
2.20.1
76
2.25.3
40
77
41
78
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We want to keep TEST_IMG for the full path of the main test image, but
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
2
5
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Insert a filter_testfiles() call between both.
4
Message-id: 20190201192935.18394-7-mreitz@redhat.com
7
5
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
tests/qemu-iotests/iotests.py | 10 ++++++++++
14
tests/qemu-iotests/iotests.py | 5 +++--
9
1 file changed, 10 insertions(+)
15
1 file changed, 3 insertions(+), 2 deletions(-)
10
16
11
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/iotests.py
19
--- a/tests/qemu-iotests/iotests.py
14
+++ b/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
15
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
16
lines.append(line)
22
for line in output.split('\n'):
17
return '\n'.join(lines)
23
if 'disk size' in line or 'actual-size' in line:
18
24
continue
19
+def filter_imgfmt(msg):
25
- line = line.replace(filename, 'TEST_IMG') \
20
+ return msg.replace(imgfmt, 'IMGFMT')
26
- .replace(imgfmt, 'IMGFMT')
21
+
27
+ line = line.replace(filename, 'TEST_IMG')
22
+def filter_qmp_imgfmt(qmsg):
28
+ line = filter_testfiles(line)
23
+ def _filter(key, value):
29
+ line = line.replace(imgfmt, 'IMGFMT')
24
+ if is_str(value):
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
25
+ return filter_imgfmt(value)
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
26
+ return value
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
27
+ return filter_qmp(qmsg, _filter)
28
+
29
def log(msg, filters=[], indent=None):
30
'''Logs either a string message or a JSON serializable message (like QMP).
31
If indent is provided, JSON serializable messages are pretty-printed.'''
32
--
33
--
33
2.20.1
34
2.25.3
34
35
35
36
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 424 insertions(+)
11
create mode 100755 tests/qemu-iotests/274
12
create mode 100644 tests/qemu-iotests/274.out
2
13
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
4
Message-id: 20190201192935.18394-32-mreitz@redhat.com
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/qemu-iotests/224 | 139 +++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/224.out | 18 +++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 158 insertions(+)
11
create mode 100755 tests/qemu-iotests/224
12
create mode 100644 tests/qemu-iotests/224.out
13
14
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
15
new file mode 100755
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
17
--- /dev/null
18
+++ b/tests/qemu-iotests/224
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python
20
+#!/usr/bin/env python3
21
+#
21
+#
22
+# Test json:{} filenames with qemu-internal BDSs
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+# (the one of commit, to be precise)
24
+#
25
+# Copyright (C) 2018 Red Hat, Inc.
26
+#
23
+#
27
+# This program is free software; you can redistribute it and/or modify
24
+# 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
25
+# 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
26
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
27
+# (at your option) any later version.
...
...
35
+# GNU General Public License for more details.
32
+# GNU General Public License for more details.
36
+#
33
+#
37
+# You should have received a copy of the GNU General Public License
34
+# 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/>.
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
36
+#
40
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
41
+
40
+
42
+import iotests
41
+import iotests
43
+from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
42
+
44
+ filter_qmp_imgfmt
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
45
+import json
46
+
47
+# Need backing file support (for arbitrary backing formats)
48
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
49
+iotests.verify_platform(['linux'])
44
+iotests.verify_platform(['linux'])
50
+
45
+
51
+
46
+size_short = 1 * 1024 * 1024
52
+# There are two variations of this test:
47
+size_long = 2 * 1024 * 1024
53
+# (1) We do not set filter_node_name. In that case, the commit_top
48
+size_diff = size_long - size_short
54
+# driver should not appear anywhere.
49
+
55
+# (2) We do set filter_node_name. In that case, it should appear.
50
+def create_chain() -> None:
56
+#
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
57
+# This for loop executes both.
52
+ str(size_long))
58
+for filter_node_name in False, True:
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
59
+ log('')
54
+ str(size_short))
60
+ log('--- filter_node_name: %s ---' % filter_node_name)
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
61
+ log('')
56
+ str(size_long))
62
+
57
+
63
+ with iotests.FilePath('base.img') as base_img_path, \
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
64
+ iotests.FilePath('mid.img') as mid_img_path, \
59
+
65
+ iotests.FilePath('top.img') as top_img_path, \
60
+def create_vm() -> iotests.VM:
66
+ iotests.VM() as vm:
61
+ vm = iotests.VM()
67
+
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
68
+ assert qemu_img('create', '-f', iotests.imgfmt,
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
69
+ base_img_path, '64M') == 0
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
70
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
71
+ mid_img_path) == 0
66
+ % iotests.imgfmt)
72
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
73
+ top_img_path) == 0
68
+ return vm
74
+
69
+
75
+ # Something to commit
70
+with iotests.FilePath('base') as base, \
76
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
71
+ iotests.FilePath('mid') as mid, \
77
+
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
78
+ vm.launch()
117
+ vm.launch()
79
+
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
80
+ # Change the bottom-most image's backing file (to null-co://)
119
+
81
+ # to enforce json:{} filenames
120
+ iotests.img_info_log(mid)
82
+ vm.qmp_log('blockdev-add',
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
83
+ node_name='top',
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
84
+ driver=iotests.imgfmt,
123
+
85
+ file={
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
86
+ 'driver': 'file',
125
+
87
+ 'filename': top_img_path
126
+ create_chain()
88
+ },
127
+ with create_vm() as vm:
89
+ backing={
128
+ vm.launch()
90
+ 'node-name': 'mid',
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
91
+ 'driver': iotests.imgfmt,
130
+ job_id='job0', auto_dismiss=False)
92
+ 'file': {
131
+ vm.run_job('job0', wait=5)
93
+ 'driver': 'file',
132
+
94
+ 'filename': mid_img_path
133
+ iotests.img_info_log(mid)
95
+ },
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
96
+ 'backing': {
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
97
+ 'node-name': 'base',
136
+
98
+ 'driver': iotests.imgfmt,
137
+
99
+ 'file': {
138
+ iotests.log('== Resize tests ==')
100
+ 'driver': 'file',
139
+
101
+ 'filename': base_img_path
140
+ # Use different sizes for different allocation modes:
102
+ },
141
+ #
103
+ 'backing': {
142
+ # We want to have at least one test where 32 bit truncation in the size of
104
+ 'driver': 'null-co'
143
+ # the overlapping area becomes visible. This is covered by the
105
+ }
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
106
+ }
145
+ #
107
+ },
146
+ # However, we can only do this for modes that don't preallocate data
108
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
147
+ # because otherwise we might run out of space on the test host.
109
+
148
+ #
110
+ # As long as block-commit does not accept node names, we have to
149
+ # We also want to test some unaligned combinations.
111
+ # get our mid/base filenames here
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
112
+ mid_name = vm.node_info('mid')['image']['filename']
151
+ ('off', '6G', '1G', '8G', '5G'),
113
+ base_name = vm.node_info('base')['image']['filename']
152
+ ('metadata', '32G', '30G', '33G', '31G'),
114
+
153
+ ('falloc', '10M', '5M', '15M', '9M'),
115
+ assert mid_name[:5] == 'json:'
154
+ ('full', '16M', '8M', '12M', '11M'),
116
+ assert base_name[:5] == 'json:'
155
+ ('off', '384k', '253k', '512k', '253k'),
117
+
156
+ ('off', '400k', '256k', '512k', '336k'),
118
+ # Start the block job
157
+ ('off', '512k', '256k', '500k', '436k')]:
119
+ if filter_node_name:
158
+
120
+ vm.qmp_log('block-commit',
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
121
+ job_id='commit',
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
122
+ device='top',
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
123
+ filter_node_name='filter_node',
162
+ top_size_old)
124
+ top=mid_name,
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
125
+ base=base_name,
164
+
126
+ speed=1,
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
127
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
166
+ #
128
+ else:
167
+ # In theory, leaving base_size to top_size_new unallocated would be
129
+ vm.qmp_log('block-commit',
168
+ # correct, but in practice, if we zero out anything, we zero out
130
+ job_id='commit',
169
+ # everything up to top_size_new.
131
+ device='top',
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
132
+ top=mid_name,
171
+ '--preallocation', prealloc, top, top_size_new)
133
+ base=base_name,
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
134
+ speed=1,
173
+ iotests.qemu_io_log('-c', 'map', top)
135
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
174
+ iotests.qemu_img_log('map', '--output=json', top)
136
+
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
137
+ vm.qmp_log('job-pause', id='commit')
138
+
139
+ # Get and parse top's json:{} filename
140
+ top_name = vm.node_info('top')['image']['filename']
141
+
142
+ vm.shutdown()
143
+
144
+ assert top_name[:5] == 'json:'
145
+ top_options = json.loads(top_name[5:])
146
+
147
+ if filter_node_name:
148
+ # This should be present and set
149
+ assert top_options['backing']['driver'] == 'commit_top'
150
+ # And the mid image is commit_top's backing image
151
+ mid_options = top_options['backing']['backing']
152
+ else:
153
+ # The mid image should appear as the immediate backing BDS
154
+ # of top
155
+ mid_options = top_options['backing']
156
+
157
+ assert mid_options['driver'] == iotests.imgfmt
158
+ assert mid_options['file']['filename'] == mid_img_path
159
diff --git a/tests/qemu-iotests/224.out b/tests/qemu-iotests/224.out
160
new file mode 100644
176
new file mode 100644
161
index XXXXXXX..XXXXXXX
177
index XXXXXXX..XXXXXXX
162
--- /dev/null
178
--- /dev/null
163
+++ b/tests/qemu-iotests/224.out
179
+++ b/tests/qemu-iotests/274.out
164
@@ -XXX,XX +XXX,XX @@
180
@@ -XXX,XX +XXX,XX @@
165
+
181
+== Commit tests ==
166
+--- filter_node_name: False ---
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
167
+
183
+
168
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
185
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
169
+{"return": {}}
285
+{"return": {}}
170
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
171
+{"return": {}}
287
+{"return": {}}
172
+{"execute": "job-pause", "arguments": {"id": "commit"}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
173
+{"return": {}}
291
+{"return": {}}
174
+
292
+image: TEST_IMG
175
+--- filter_node_name: True ---
293
+file format: IMGFMT
176
+
294
+virtual size: 2 MiB (2097152 bytes)
177
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
295
+cluster_size: 65536
178
+{"return": {}}
296
+backing file: TEST_DIR/PID-base
179
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "filter-node-name": "filter_node", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
297
+Format specific information:
180
+{"return": {}}
298
+ compat: 1.1
181
+{"execute": "job-pause", "arguments": {"id": "commit"}}
299
+ lazy refcounts: false
182
+{"return": {}}
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
183
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
184
index XXXXXXX..XXXXXXX 100644
450
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qemu-iotests/group
451
--- a/tests/qemu-iotests/group
186
+++ b/tests/qemu-iotests/group
452
+++ b/tests/qemu-iotests/group
187
@@ -XXX,XX +XXX,XX @@
453
@@ -XXX,XX +XXX,XX @@
188
221 rw auto quick
454
270 rw backing quick
189
222 rw auto quick
455
272 rw
190
223 rw auto quick
456
273 backing quick
191
+224 rw auto quick
457
+274 rw backing
192
225 rw auto quick
458
277 rw quick
193
226 auto quick
459
279 rw backing quick
194
227 auto quick
460
280 rw migration quick
195
--
461
--
196
2.20.1
462
2.25.3
197
463
198
464
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
2
image is possibly preallocated and then the zero flag is added to all
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
2
6
3
LUKS encryption reserves clusters for its own payload data. The size of
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
4
this area must be included in the qemu-img measure calculation so that
8
and if the protocol driver can ensure that the new area reads as zeros,
5
we arrive at the correct minimum required image size.
9
we can skip setting the zero flag in the qcow2 layer.
6
10
7
(Ab)use the qcrypto_block_create() API to determine the payload
11
Unfortunately, the same approach doesn't work for metadata
8
overhead. We discard the payload data that qcrypto thinks will be
12
preallocation, so we'll still set the zero flag there.
9
written to the image.
10
13
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20190218104525.23674-2-stefanha@redhat.com
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
19
---
16
block/qcow2.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
20
block/qcow2.c | 22 +++++++++++++++++++---
17
1 file changed, 71 insertions(+), 1 deletion(-)
21
tests/qemu-iotests/274.out | 4 ++--
22
2 files changed, 21 insertions(+), 5 deletions(-)
18
23
19
diff --git a/block/qcow2.c b/block/qcow2.c
24
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
26
--- a/block/qcow2.c
22
+++ b/block/qcow2.c
27
+++ b/block/qcow2.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
24
return ret;
29
/* Allocate the data area */
25
}
30
new_file_size = allocation_start +
26
31
nb_new_data_clusters * s->cluster_size;
27
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
32
- /* Image file grows, so @exact does not matter */
28
+ size_t headerlen, void *opaque, Error **errp)
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
29
+{
34
- errp);
30
+ size_t *headerlenp = opaque;
35
+ /*
31
+
36
+ * Image file grows, so @exact does not matter.
32
+ /* Stash away the payload size */
37
+ *
33
+ *headerlenp = headerlen;
38
+ * If we need to zero out the new area, try first whether the protocol
34
+ return 0;
39
+ * driver can already take care of this.
35
+}
40
+ */
36
+
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
37
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
38
+ size_t offset, const uint8_t *buf, size_t buflen,
43
+ BDRV_REQ_ZERO_WRITE, NULL);
39
+ void *opaque, Error **errp)
44
+ if (ret >= 0) {
40
+{
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
41
+ /* Discard the bytes, we're not actually writing to an image */
46
+ }
42
+ return buflen;
47
+ } else {
43
+}
48
+ ret = -1;
44
+
45
+/* Determine the number of bytes for the LUKS payload */
46
+static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
47
+ Error **errp)
48
+{
49
+ QDict *opts_qdict;
50
+ QDict *cryptoopts_qdict;
51
+ QCryptoBlockCreateOptions *cryptoopts;
52
+ QCryptoBlock *crypto;
53
+
54
+ /* Extract "encrypt." options into a qdict */
55
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
56
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
57
+ qobject_unref(opts_qdict);
58
+
59
+ /* Build QCryptoBlockCreateOptions object from qdict */
60
+ qdict_put_str(cryptoopts_qdict, "format", "luks");
61
+ cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
62
+ qobject_unref(cryptoopts_qdict);
63
+ if (!cryptoopts) {
64
+ return false;
65
+ }
66
+
67
+ /* Fake LUKS creation in order to determine the payload size */
68
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
69
+ qcow2_measure_crypto_hdr_init_func,
70
+ qcow2_measure_crypto_hdr_write_func,
71
+ len, errp);
72
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
73
+ if (!crypto) {
74
+ return false;
75
+ }
76
+
77
+ qcrypto_block_free(crypto);
78
+ return true;
79
+}
80
+
81
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
82
Error **errp)
83
{
84
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
85
uint64_t virtual_size; /* disk size as seen by guest */
86
uint64_t refcount_bits;
87
uint64_t l2_tables;
88
+ uint64_t luks_payload_size = 0;
89
size_t cluster_size;
90
int version;
91
char *optstr;
92
PreallocMode prealloc;
93
bool has_backing_file;
94
+ bool has_luks;
95
96
/* Parse image creation options */
97
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
98
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
99
has_backing_file = !!optstr;
100
g_free(optstr);
101
102
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
103
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
104
+ g_free(optstr);
105
+
106
+ if (has_luks) {
107
+ size_t headerlen;
108
+
109
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
110
+ goto err;
111
+ }
49
+ }
112
+
50
+ if (ret < 0) {
113
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
114
+ }
52
+ errp);
115
+
53
+ }
116
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
54
if (ret < 0) {
117
virtual_size = ROUND_UP(virtual_size, cluster_size);
55
error_prepend(errp, "Failed to resize underlying file: ");
118
56
qcow2_free_clusters(bs, allocation_start,
119
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
120
info = g_new(BlockMeasureInfo, 1);
58
index XXXXXXX..XXXXXXX 100644
121
info->fully_allocated =
59
--- a/tests/qemu-iotests/274.out
122
qcow2_calc_prealloc_size(virtual_size, cluster_size,
60
+++ b/tests/qemu-iotests/274.out
123
- ctz32(refcount_bits));
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
124
+ ctz32(refcount_bits)) + luks_payload_size;
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
125
63
126
/* Remove data clusters that are not required. This overestimates the
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
127
* required size because metadata needed for the fully allocated file is
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
128
--
79
--
129
2.20.1
80
2.25.3
130
81
131
82
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
2
2
3
Currently, BlockDriver.bdrv_refresh_filename() is supposed to both
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
refresh the filename (BDS.exact_filename) and set BDS.full_open_options.
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
Now that we have generic code in the central bdrv_refresh_filename() for
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
creating BDS.full_open_options, we can drop the latter part from all
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
BlockDriver.bdrv_refresh_filename() implementations.
7
persistent across system reboot.
8
8
9
This also means that we can drop all of the existing default code for
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
10
this from the global bdrv_refresh_filename() itself.
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
hw/block/nvme.h | 2 +
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
11
22
12
Furthermore, we now have to call BlockDriver.bdrv_refresh_filename()
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
13
after having set BDS.full_open_options, because the block driver's
14
implementation should now be allowed to depend on BDS.full_open_options
15
being set correctly.
16
17
Finally, with this patch we can drop the @options parameter from
18
BlockDriver.bdrv_refresh_filename(); also, add a comment on this
19
function's purpose in block/block_int.h while touching its interface.
20
21
This completely obsoletes blklogwrite's implementation of
22
.bdrv_refresh_filename().
23
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
Message-id: 20190201192935.18394-25-mreitz@redhat.com
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
include/block/block_int.h | 6 +-
29
block.c | 131 +++++++------------------------------
30
block/blkdebug.c | 54 ++++++---------
31
block/blklogwrites.c | 22 -------
32
block/blkverify.c | 16 +----
33
block/commit.c | 2 +-
34
block/mirror.c | 2 +-
35
block/nbd.c | 23 +------
36
block/nfs.c | 36 +---------
37
block/null.c | 22 ++++---
38
block/nvme.c | 22 ++++---
39
block/quorum.c | 30 ---------
40
tests/qemu-iotests/228 | 4 --
41
tests/qemu-iotests/228.out | 2 +-
42
14 files changed, 81 insertions(+), 291 deletions(-)
43
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
25
--- a/hw/block/nvme.h
47
+++ b/include/block/block_int.h
26
+++ b/hw/block/nvme.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
49
Error **errp);
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
50
int (*bdrv_make_empty)(BlockDriverState *bs);
29
51
30
char *serial;
52
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
31
+ HostMemoryBackend *pmrdev;
53
+ /*
32
+
54
+ * Refreshes the bs->exact_filename field. If that is impossible,
33
NvmeNamespace *namespaces;
55
+ * bs->exact_filename has to be left empty.
34
NvmeSQueue **sq;
56
+ */
35
NvmeCQueue **cq;
57
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
58
59
/*
60
* Gathers the open options for all children into @target.
61
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
38
--- a/include/block/nvme.h
64
+++ b/block.c
39
+++ b/include/block/nvme.h
65
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
66
return found_any;
41
uint64_t acq;
67
}
42
uint32_t cmbloc;
68
43
uint32_t cmbsz;
69
-static bool append_open_options(QDict *d, BlockDriverState *bs)
44
+ uint8_t padding[3520]; /* not used by QEMU */
70
-{
45
+ uint32_t pmrcap;
71
- const QDictEntry *entry;
46
+ uint32_t pmrctl;
72
- QemuOptDesc *desc;
47
+ uint32_t pmrsts;
73
- bool found_any = false;
48
+ uint32_t pmrebs;
74
-
49
+ uint32_t pmrswtp;
75
- for (entry = qdict_first(bs->options); entry;
50
+ uint32_t pmrmsc;
76
- entry = qdict_next(bs->options, entry))
51
} NvmeBar;
77
- {
52
78
- /* Exclude all non-driver-specific options */
53
enum NvmeCapShift {
79
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
80
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
55
CAP_CSS_SHIFT = 37,
81
- break;
56
CAP_MPSMIN_SHIFT = 48,
82
- }
57
CAP_MPSMAX_SHIFT = 52,
83
- }
58
+ CAP_PMR_SHIFT = 56,
84
- if (desc->name) {
59
};
85
- continue;
60
86
- }
61
enum NvmeCapMask {
87
-
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
88
- qdict_put_obj(d, qdict_entry_key(entry),
63
CAP_CSS_MASK = 0xff,
89
- qobject_ref(qdict_entry_value(entry)));
64
CAP_MPSMIN_MASK = 0xf,
90
- found_any = true;
65
CAP_MPSMAX_MASK = 0xf,
91
- }
66
+ CAP_PMR_MASK = 0x1,
92
-
67
};
93
- return found_any;
68
94
-}
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
95
-
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
96
/* Note: This function may return false positives; it may return true
71
<< CAP_MPSMIN_SHIFT)
97
* even if opening the backing file specified by bs's image header
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
98
* would result in exactly bs->backing. */
73
<< CAP_MPSMAX_SHIFT)
99
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
100
BdrvChild *child;
75
+ << CAP_PMR_SHIFT)
101
QDict *opts;
76
102
bool backing_overridden;
77
enum NvmeCcShift {
103
+ bool generate_json_filename; /* Whether our default implementation should
78
CC_EN_SHIFT = 0,
104
+ fill exact_filename (false) or not (true) */
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
105
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
106
if (!drv) {
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
107
return;
284
return;
108
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
285
+ case 0xE00: /* PMRCAP */
109
backing_overridden = false;
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
110
}
309
}
111
310
112
- if (drv->bdrv_refresh_filename) {
311
if (addr < sizeof(n->bar)) {
113
- /* Obsolete information is of no use here, so drop the old file name
312
+ /*
114
- * information before refreshing it */
313
+ * When PMRWBM bit 1 is set then read from
115
- bs->exact_filename[0] = '\0';
314
+ * from PMRSTS should ensure prior writes
116
- if (bs->full_open_options) {
315
+ * made it to persistent media
117
- qobject_unref(bs->full_open_options);
316
+ */
118
- bs->full_open_options = NULL;
317
+ if (addr == 0xE08 &&
119
- }
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
120
-
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
121
- opts = qdict_new();
320
+ 0, n->pmrdev->size);
122
- append_open_options(opts, bs);
123
- drv->bdrv_refresh_filename(bs, opts);
124
- qobject_unref(opts);
125
- } else if (bs->file) {
126
- /* Try to reconstruct valid information from the underlying file */
127
- bool has_open_options;
128
-
129
- bs->exact_filename[0] = '\0';
130
- if (bs->full_open_options) {
131
- qobject_unref(bs->full_open_options);
132
- bs->full_open_options = NULL;
133
- }
134
-
135
- opts = qdict_new();
136
- has_open_options = append_open_options(opts, bs);
137
- has_open_options |= backing_overridden;
138
-
139
- /* If no specific options have been given for this BDS, the filename of
140
- * the underlying file should suffice for this one as well */
141
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
142
- strcpy(bs->exact_filename, bs->file->bs->exact_filename);
143
- }
144
- /* Reconstructing the full options QDict is simple for most format block
145
- * drivers, as long as the full options are known for the underlying
146
- * file BDS. The full options QDict of that file BDS should somehow
147
- * contain a representation of the filename, therefore the following
148
- * suffices without querying the (exact_)filename of this BDS. */
149
- if (bs->file->bs->full_open_options &&
150
- (!bs->backing || bs->backing->bs->full_open_options))
151
- {
152
- qdict_put_str(opts, "driver", drv->format_name);
153
- qdict_put(opts, "file",
154
- qobject_ref(bs->file->bs->full_open_options));
155
-
156
- if (bs->backing) {
157
- qdict_put(opts, "backing",
158
- qobject_ref(bs->backing->bs->full_open_options));
159
- } else if (backing_overridden) {
160
- qdict_put_null(opts, "backing");
161
- }
162
-
163
- bs->full_open_options = opts;
164
- } else {
165
- qobject_unref(opts);
166
- }
167
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
168
- /* There is no underlying file BDS (at least referenced by BDS.file),
169
- * so the full options QDict should be equal to the options given
170
- * specifically for this block device when it was opened (plus the
171
- * driver specification).
172
- * Because those options don't change, there is no need to update
173
- * full_open_options when it's already set. */
174
-
175
- opts = qdict_new();
176
- append_open_options(opts, bs);
177
- qdict_put_str(opts, "driver", drv->format_name);
178
-
179
- if (bs->exact_filename[0]) {
180
- /* This may not work for all block protocol drivers (some may
181
- * require this filename to be parsed), but we have to find some
182
- * default solution here, so just include it. If some block driver
183
- * does not support pure options without any filename at all or
184
- * needs some special format of the options QDict, it needs to
185
- * implement the driver-specific bdrv_refresh_filename() function.
186
- */
187
- qdict_put_str(opts, "filename", bs->exact_filename);
188
- }
189
-
190
- bs->full_open_options = opts;
191
- }
192
-
193
/* Gather the options QDict */
194
opts = qdict_new();
195
- append_strong_runtime_options(opts, bs);
196
+ generate_json_filename = append_strong_runtime_options(opts, bs);
197
+ generate_json_filename |= backing_overridden;
198
199
if (drv->bdrv_gather_child_options) {
200
/* Some block drivers may not want to present all of their children's
201
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
202
qobject_unref(bs->full_open_options);
203
bs->full_open_options = opts;
204
205
+ if (drv->bdrv_refresh_filename) {
206
+ /* Obsolete information is of no use here, so drop the old file name
207
+ * information before refreshing it */
208
+ bs->exact_filename[0] = '\0';
209
+
210
+ drv->bdrv_refresh_filename(bs);
211
+ } else if (bs->file) {
212
+ /* Try to reconstruct valid information from the underlying file */
213
+
214
+ bs->exact_filename[0] = '\0';
215
+
216
+ /* If no specific options have been given for this BDS, the filename of
217
+ * the underlying file should suffice for this one as well */
218
+ if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
219
+ strcpy(bs->exact_filename, bs->file->bs->exact_filename);
220
+ }
321
+ }
221
+ }
322
memcpy(&val, ptr + addr, size);
222
+
223
if (bs->exact_filename[0]) {
224
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
225
} else {
323
} else {
226
diff --git a/block/blkdebug.c b/block/blkdebug.c
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
227
index XXXXXXX..XXXXXXX 100644
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
228
--- a/block/blkdebug.c
326
error_setg(errp, "serial property not set");
229
+++ b/block/blkdebug.c
230
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
231
return bdrv_getlength(bs->file->bs);
232
}
233
234
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
235
+static void blkdebug_refresh_filename(BlockDriverState *bs)
236
{
237
BDRVBlkdebugState *s = bs->opaque;
238
- QDict *opts;
239
const QDictEntry *e;
240
- bool force_json = false;
241
-
242
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
243
- if (strcmp(qdict_entry_key(e), "config") &&
244
- strcmp(qdict_entry_key(e), "x-image"))
245
- {
246
- force_json = true;
247
- break;
248
- }
249
- }
250
+ int ret;
251
252
- if (force_json && !bs->file->bs->full_open_options) {
253
- /* The config file cannot be recreated, so creating a plain filename
254
- * is impossible */
255
+ if (!bs->file->bs->exact_filename[0]) {
256
return;
327
return;
257
}
328
}
258
329
+
259
- if (!force_json && bs->file->bs->exact_filename[0]) {
330
+ if (!n->cmb_size_mb && n->pmrdev) {
260
- int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
261
- "blkdebug:%s:%s", s->config_file ?: "",
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
262
- bs->file->bs->exact_filename);
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
263
- if (ret >= sizeof(bs->exact_filename)) {
334
+ g_free(path);
264
- /* An overflow makes the filename unusable, so do not report any */
265
- bs->exact_filename[0] = 0;
266
+ for (e = qdict_first(bs->full_open_options); e;
267
+ e = qdict_next(bs->full_open_options, e))
268
+ {
269
+ /* Real child options are under "image", but "x-image" may
270
+ * contain a filename */
271
+ if (strcmp(qdict_entry_key(e), "config") &&
272
+ strcmp(qdict_entry_key(e), "image") &&
273
+ strcmp(qdict_entry_key(e), "x-image") &&
274
+ strcmp(qdict_entry_key(e), "driver"))
275
+ {
276
+ return;
277
}
278
}
279
280
- opts = qdict_new();
281
- qdict_put_str(opts, "driver", "blkdebug");
282
-
283
- qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options));
284
-
285
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
286
- if (strcmp(qdict_entry_key(e), "x-image")) {
287
- qdict_put_obj(opts, qdict_entry_key(e),
288
- qobject_ref(qdict_entry_value(e)));
289
- }
290
+ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
291
+ "blkdebug:%s:%s",
292
+ s->config_file ?: "", bs->file->bs->exact_filename);
293
+ if (ret >= sizeof(bs->exact_filename)) {
294
+ /* An overflow makes the filename unusable, so do not report any */
295
+ bs->exact_filename[0] = 0;
296
}
297
-
298
- bs->full_open_options = opts;
299
}
300
301
static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
302
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/block/blklogwrites.c
305
+++ b/block/blklogwrites.c
306
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
307
return bdrv_getlength(bs->file->bs);
308
}
309
310
-static void blk_log_writes_refresh_filename(BlockDriverState *bs,
311
- QDict *options)
312
-{
313
- BDRVBlkLogWritesState *s = bs->opaque;
314
-
315
- if (bs->file->bs->full_open_options
316
- && s->log_file->bs->full_open_options)
317
- {
318
- QDict *opts = qdict_new();
319
- qdict_put_str(opts, "driver", "blklogwrites");
320
-
321
- qobject_ref(bs->file->bs->full_open_options);
322
- qdict_put(opts, "file", bs->file->bs->full_open_options);
323
- qobject_ref(s->log_file->bs->full_open_options);
324
- qdict_put(opts, "log", s->log_file->bs->full_open_options);
325
- qdict_put_int(opts, "log-sector-size", s->sectorsize);
326
-
327
- bs->full_open_options = opts;
328
- }
329
-}
330
-
331
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
332
const BdrvChildRole *role,
333
BlockReopenQueue *ro_q,
334
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
335
.bdrv_open = blk_log_writes_open,
336
.bdrv_close = blk_log_writes_close,
337
.bdrv_getlength = blk_log_writes_getlength,
338
- .bdrv_refresh_filename = blk_log_writes_refresh_filename,
339
.bdrv_child_perm = blk_log_writes_child_perm,
340
.bdrv_refresh_limits = blk_log_writes_refresh_limits,
341
342
diff --git a/block/blkverify.c b/block/blkverify.c
343
index XXXXXXX..XXXXXXX 100644
344
--- a/block/blkverify.c
345
+++ b/block/blkverify.c
346
@@ -XXX,XX +XXX,XX @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
347
return bdrv_recurse_is_first_non_filter(s->test_file->bs, candidate);
348
}
349
350
-static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
351
+static void blkverify_refresh_filename(BlockDriverState *bs)
352
{
353
BDRVBlkverifyState *s = bs->opaque;
354
355
- if (bs->file->bs->full_open_options
356
- && s->test_file->bs->full_open_options)
357
- {
358
- QDict *opts = qdict_new();
359
- qdict_put_str(opts, "driver", "blkverify");
360
-
361
- qdict_put(opts, "raw",
362
- qobject_ref(bs->file->bs->full_open_options));
363
- qdict_put(opts, "test",
364
- qobject_ref(s->test_file->bs->full_open_options));
365
-
366
- bs->full_open_options = opts;
367
- }
368
-
369
if (bs->file->bs->exact_filename[0]
370
&& s->test_file->bs->exact_filename[0])
371
{
372
diff --git a/block/commit.c b/block/commit.c
373
index XXXXXXX..XXXXXXX 100644
374
--- a/block/commit.c
375
+++ b/block/commit.c
376
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
377
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
378
}
379
380
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
381
+static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
382
{
383
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
384
bs->backing->bs->filename);
385
diff --git a/block/mirror.c b/block/mirror.c
386
index XXXXXXX..XXXXXXX 100644
387
--- a/block/mirror.c
388
+++ b/block/mirror.c
389
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
390
NULL, 0);
391
}
392
393
-static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
394
+static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
395
{
396
if (bs->backing == NULL) {
397
/* we can be here after failed bdrv_attach_child in
398
diff --git a/block/nbd.c b/block/nbd.c
399
index XXXXXXX..XXXXXXX 100644
400
--- a/block/nbd.c
401
+++ b/block/nbd.c
402
@@ -XXX,XX +XXX,XX @@ static void nbd_attach_aio_context(BlockDriverState *bs,
403
nbd_client_attach_aio_context(bs, new_context);
404
}
405
406
-static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
407
+static void nbd_refresh_filename(BlockDriverState *bs)
408
{
409
BDRVNBDState *s = bs->opaque;
410
- QDict *opts = qdict_new();
411
- QObject *saddr_qdict;
412
- Visitor *ov;
413
const char *host = NULL, *port = NULL, *path = NULL;
414
415
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
416
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
417
path = s->saddr->u.q_unix.path;
418
} /* else can't represent as pseudo-filename */
419
420
- qdict_put_str(opts, "driver", "nbd");
421
-
422
if (path && s->export) {
423
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
424
"nbd+unix:///%s?socket=%s", s->export, path);
425
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
426
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
427
"nbd://%s:%s", host, port);
428
}
429
-
430
- ov = qobject_output_visitor_new(&saddr_qdict);
431
- visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
432
- visit_complete(ov, &saddr_qdict);
433
- visit_free(ov);
434
- qdict_put_obj(opts, "server", saddr_qdict);
435
-
436
- if (s->export) {
437
- qdict_put_str(opts, "export", s->export);
438
- }
439
- if (s->tlscredsid) {
440
- qdict_put_str(opts, "tls-creds", s->tlscredsid);
441
- }
442
-
443
- qdict_flatten(opts);
444
- bs->full_open_options = opts;
445
}
446
447
static char *nbd_dirname(BlockDriverState *bs, Error **errp)
448
diff --git a/block/nfs.c b/block/nfs.c
449
index XXXXXXX..XXXXXXX 100644
450
--- a/block/nfs.c
451
+++ b/block/nfs.c
452
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
453
return 0;
454
}
455
456
-static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
457
+static void nfs_refresh_filename(BlockDriverState *bs)
458
{
459
NFSClient *client = bs->opaque;
460
- QDict *opts = qdict_new();
461
- QObject *server_qdict;
462
- Visitor *ov;
463
-
464
- qdict_put_str(opts, "driver", "nfs");
465
466
if (client->uid && !client->gid) {
467
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
468
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
469
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
470
"nfs://%s%s", client->server->host, client->path);
471
}
472
-
473
- ov = qobject_output_visitor_new(&server_qdict);
474
- visit_type_NFSServer(ov, NULL, &client->server, &error_abort);
475
- visit_complete(ov, &server_qdict);
476
- qdict_put_obj(opts, "server", server_qdict);
477
- qdict_put_str(opts, "path", client->path);
478
-
479
- if (client->uid) {
480
- qdict_put_int(opts, "user", client->uid);
481
- }
482
- if (client->gid) {
483
- qdict_put_int(opts, "group", client->gid);
484
- }
485
- if (client->tcp_syncnt) {
486
- qdict_put_int(opts, "tcp-syn-cnt", client->tcp_syncnt);
487
- }
488
- if (client->readahead) {
489
- qdict_put_int(opts, "readahead-size", client->readahead);
490
- }
491
- if (client->pagecache) {
492
- qdict_put_int(opts, "page-cache-size", client->pagecache);
493
- }
494
- if (client->debug) {
495
- qdict_put_int(opts, "debug", client->debug);
496
- }
497
-
498
- visit_free(ov);
499
- qdict_flatten(opts);
500
- bs->full_open_options = opts;
501
}
502
503
static char *nfs_dirname(BlockDriverState *bs, Error **errp)
504
diff --git a/block/null.c b/block/null.c
505
index XXXXXXX..XXXXXXX 100644
506
--- a/block/null.c
507
+++ b/block/null.c
508
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn null_co_block_status(BlockDriverState *bs,
509
return ret;
510
}
511
512
-static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
513
+static void null_refresh_filename(BlockDriverState *bs)
514
{
515
- qdict_del(opts, "filename");
516
-
517
- if (!qdict_size(opts)) {
518
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
519
- bs->drv->format_name);
520
+ const QDictEntry *e;
521
+
522
+ for (e = qdict_first(bs->full_open_options); e;
523
+ e = qdict_next(bs->full_open_options, e))
524
+ {
525
+ /* These options can be ignored */
526
+ if (strcmp(qdict_entry_key(e), "filename") &&
527
+ strcmp(qdict_entry_key(e), "driver"))
528
+ {
529
+ return;
335
+ return;
530
+ }
336
+ }
531
}
337
+
532
338
+ if (!is_power_of_2(n->pmrdev->size)) {
533
- qdict_put_str(opts, "driver", bs->drv->format_name);
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
534
- bs->full_open_options = qobject_ref(opts);
535
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
536
+ bs->drv->format_name);
537
}
538
539
static const char *const null_strong_runtime_opts[] = {
540
diff --git a/block/nvme.c b/block/nvme.c
541
index XXXXXXX..XXXXXXX 100644
542
--- a/block/nvme.c
543
+++ b/block/nvme.c
544
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
545
return 0;
546
}
547
548
-static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
549
+static void nvme_refresh_filename(BlockDriverState *bs)
550
{
551
- qdict_del(opts, "filename");
552
-
553
- if (!qdict_size(opts)) {
554
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
555
- bs->drv->format_name);
556
+ const QDictEntry *e;
557
+
558
+ for (e = qdict_first(bs->full_open_options); e;
559
+ e = qdict_next(bs->full_open_options, e))
560
+ {
561
+ /* These options can be ignored */
562
+ if (strcmp(qdict_entry_key(e), "filename") &&
563
+ strcmp(qdict_entry_key(e), "driver"))
564
+ {
565
+ return;
340
+ return;
566
+ }
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
344
+ }
345
+
346
blkconf_blocksizes(&n->conf);
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
348
false, errp)) {
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
352
353
+ } else if (n->pmrdev) {
354
+ /* Controller Capabilities register */
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
356
+
357
+ /* PMR Capabities register */
358
+ n->bar.pmrcap = 0;
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
567
}
398
}
568
399
569
- qdict_put_str(opts, "driver", bs->drv->format_name);
400
for (i = 0; i < n->num_namespaces; i++) {
570
- bs->full_open_options = qobject_ref(opts);
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
571
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
402
if (n->cmb_size_mb) {
572
+ bs->drv->format_name);
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
573
}
410
}
574
411
575
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
412
static Property nvme_props[] = {
576
diff --git a/block/quorum.c b/block/quorum.c
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
577
index XXXXXXX..XXXXXXX 100644
420
index XXXXXXX..XXXXXXX 100644
578
--- a/block/quorum.c
421
--- a/hw/block/Makefile.objs
579
+++ b/block/quorum.c
422
+++ b/hw/block/Makefile.objs
580
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
581
bdrv_drained_end(bs);
424
common-obj-$(CONFIG_XEN) += xen-block.o
582
}
425
common-obj-$(CONFIG_ECC) += ecc.o
583
426
common-obj-$(CONFIG_ONENAND) += onenand.o
584
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
585
-{
428
common-obj-$(CONFIG_SWIM) += swim.o
586
- BDRVQuorumState *s = bs->opaque;
429
587
- QDict *opts;
430
common-obj-$(CONFIG_SH4) += tc58128.o
588
- QList *children;
431
589
- int i;
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
590
-
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
591
- for (i = 0; i < s->num_children; i++) {
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
592
- if (!s->children[i]->bs->full_open_options) {
435
593
- return;
436
obj-y += dataplane/
594
- }
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
595
- }
596
-
597
- children = qlist_new();
598
- for (i = 0; i < s->num_children; i++) {
599
- qlist_append(children,
600
- qobject_ref(s->children[i]->bs->full_open_options));
601
- }
602
-
603
- opts = qdict_new();
604
- qdict_put_str(opts, "driver", "quorum");
605
- qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold);
606
- qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify);
607
- qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted);
608
- qdict_put(opts, "children", children);
609
-
610
- bs->full_open_options = opts;
611
-}
612
-
613
static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
614
bool backing_overridden)
615
{
616
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
617
618
.bdrv_open = quorum_open,
619
.bdrv_close = quorum_close,
620
- .bdrv_refresh_filename = quorum_refresh_filename,
621
.bdrv_gather_child_options = quorum_gather_child_options,
622
.bdrv_dirname = quorum_dirname,
623
624
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
625
index XXXXXXX..XXXXXXX 100755
626
--- a/tests/qemu-iotests/228
627
+++ b/tests/qemu-iotests/228
628
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
629
overlay='node0')
630
631
# This should give us the original plain result
632
- # FIXME: Currently, it yields a json:{} filename even though it
633
- # only contains a @driver and a @file entry, so a plain
634
- # filename would obviously suffice. This is fixed by a
635
- # future patch.
636
637
log_node_info(vm.node_info('node0'))
638
639
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
640
index XXXXXXX..XXXXXXX 100644
438
index XXXXXXX..XXXXXXX 100644
641
--- a/tests/qemu-iotests/228.out
439
--- a/hw/block/trace-events
642
+++ b/tests/qemu-iotests/228.out
440
+++ b/hw/block/trace-events
643
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
644
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
645
{"return": {}}
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
646
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
647
-bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
648
+bs->filename: TEST_DIR/PID-top.img
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
649
bs->backing_file: TEST_DIR/PID-base.img
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
650
bs->backing->bs->filename: TEST_DIR/PID-base.img
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
651
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
652
--
452
--
653
2.20.1
453
2.25.3
654
454
655
455
diff view generated by jsdifflib
1
Now that bdrv_set_aio_context() works inside drained sections, it can
1
The QMP handler qmp_object_add() and the implementation of --object in
2
also use the real drain function instead of open coding something
2
qemu-storage-daemon can share most of the code. Currently,
3
similar.
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
5
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
7
new function user_creatable_add_dict() that can get an additional
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
4
11
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
13
---
7
block.c | 15 ++++++---------
14
include/qom/object_interfaces.h | 12 ++++++++++++
8
1 file changed, 6 insertions(+), 9 deletions(-)
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
17
3 files changed, 40 insertions(+), 23 deletions(-)
9
18
10
diff --git a/block.c b/block.c
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/block.c
21
--- a/include/qom/object_interfaces.h
13
+++ b/block.c
22
+++ b/include/qom/object_interfaces.h
14
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
15
bs->walking_aio_notifiers = false;
24
const QDict *qdict,
25
Visitor *v, Error **errp);
26
27
+/**
28
+ * user_creatable_add_dict:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
32
+ * Create an instance of the user creatable object that is defined by
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
45
+++ b/qom/object_interfaces.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
51
#include "qom/object_interfaces.h"
52
#include "qemu/help_option.h"
53
#include "qemu/module.h"
54
@@ -XXX,XX +XXX,XX @@ out:
55
return obj;
16
}
56
}
17
57
18
+/* The caller must own the AioContext lock for the old AioContext of bs, but it
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
19
+ * must not own the AioContext lock for new_context (unless new_context is
59
+{
20
+ * the same as the current context of bs). */
60
+ Visitor *v;
21
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
61
+ Object *obj;
62
+ g_autofree char *type = NULL;
63
+ g_autofree char *id = NULL;
64
+
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
22
{
86
{
23
- AioContext *ctx = bdrv_get_aio_context(bs);
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
90
+++ b/qom/qom-qmp-cmds.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/qapi-commands-qom.h"
93
#include "qapi/qmp/qdict.h"
94
#include "qapi/qmp/qerror.h"
95
-#include "qapi/qobject-input-visitor.h"
96
#include "qemu/cutils.h"
97
#include "qom/object_interfaces.h"
98
#include "qom/qom-qobject.h"
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
24
-
107
-
25
- if (ctx == new_context) {
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
26
+ if (bdrv_get_aio_context(bs) == new_context) {
109
- if (!type) {
27
return;
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
28
}
126
}
29
127
30
- aio_disable_external(ctx);
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
31
- bdrv_parent_drained_begin(bs, NULL, false);
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
32
- bdrv_drain(bs); /* ensure there are no in-flight requests */
130
- visit_free(v);
33
-
131
- object_unref(obj);
34
+ bdrv_drained_begin(bs);
132
+ user_creatable_add_dict(qdict, errp);
35
bdrv_detach_aio_context(bs);
36
37
/* This function executes in the old AioContext so acquire the new one in
38
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
39
*/
40
aio_context_acquire(new_context);
41
bdrv_attach_aio_context(bs, new_context);
42
- bdrv_parent_drained_end(bs, NULL, false);
43
- aio_enable_external(ctx);
44
+ bdrv_drained_end(bs);
45
aio_context_release(new_context);
46
}
133
}
47
134
135
void qmp_object_del(const char *id, Error **errp)
48
--
136
--
49
2.20.1
137
2.25.3
50
138
51
139
diff view generated by jsdifflib
1
Similar to how qemu_co_sleep_ns() allows preemption from an external
1
After processing the option string with the keyval parser, we get a
2
coroutine entry, allow reentering qio_channel_yield() early.
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
3
4
5
qmp_object_add(), however, uses the normal QObject input visitor, which
6
expects a QDict where all properties already have the QType that matches
7
the data type required by the QOM object type.
8
9
Change the --object implementation in qemu-storage-daemon so that it
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
16
---
6
include/io/channel.h | 9 ++++++---
17
include/qom/object_interfaces.h | 6 +++++-
7
io/channel.c | 10 ++++++++++
18
qemu-storage-daemon.c | 4 +---
8
2 files changed, 16 insertions(+), 3 deletions(-)
19
qom/object_interfaces.c | 8 ++++++--
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
9
22
10
diff --git a/include/io/channel.h b/include/io/channel.h
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
11
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
12
--- a/include/io/channel.h
25
--- a/include/qom/object_interfaces.h
13
+++ b/include/io/channel.h
26
+++ b/include/qom/object_interfaces.h
14
@@ -XXX,XX +XXX,XX @@ void qio_channel_detach_aio_context(QIOChannel *ioc);
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
15
* addition, no two coroutine can be waiting on the same condition
28
/**
16
* and channel at the same time.
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
17
*
36
*
18
- * This must only be called from coroutine context
37
* Create an instance of the user creatable object that is defined by
19
+ * This must only be called from coroutine context. It is safe to
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
20
+ * reenter the coroutine externally while it is waiting; in this
39
* ID from the key 'id'. The remaining entries in @qdict are used to
21
+ * case the function will return even if @condition is not yet
40
* initialize the object properties.
22
+ * available.
23
*/
41
*/
24
-void qio_channel_yield(QIOChannel *ioc,
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
25
- GIOCondition condition);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
26
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
27
+ GIOCondition condition);
28
44
29
/**
45
/**
30
* qio_channel_wait:
46
* user_creatable_add_opts:
31
diff --git a/io/channel.c b/io/channel.c
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
32
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
33
--- a/io/channel.c
49
--- a/qemu-storage-daemon.c
34
+++ b/io/channel.c
50
+++ b/qemu-storage-daemon.c
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qio_channel_yield(QIOChannel *ioc,
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
76
}
77
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
80
{
81
Visitor *v;
82
Object *obj;
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
36
}
84
}
37
qio_channel_set_aio_fd_handlers(ioc);
85
qdict_del(qdict, "id");
38
qemu_coroutine_yield();
86
39
+
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
40
+ /* Allow interrupting the operation by reentering the coroutine other than
88
+ if (keyval) {
41
+ * through the aio_fd_handlers. */
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
42
+ if (condition == G_IO_IN && ioc->read_coroutine) {
90
+ } else {
43
+ ioc->read_coroutine = NULL;
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
44
+ qio_channel_set_aio_fd_handlers(ioc);
45
+ } else if (condition == G_IO_OUT && ioc->write_coroutine) {
46
+ ioc->write_coroutine = NULL;
47
+ qio_channel_set_aio_fd_handlers(ioc);
48
+ }
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
49
}
106
}
50
107
51
108
void qmp_object_del(const char *id, Error **errp)
52
--
109
--
53
2.20.1
110
2.25.3
54
111
55
112
diff view generated by jsdifflib
Deleted patch
1
The only caller of nbd_read_eof() is nbd_receive_reply(), so it doesn't
2
have to live in the header file, but can move next to its caller.
3
1
4
Also add the missing coroutine_fn to the function and its caller.
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
9
include/block/nbd.h | 3 ++-
10
nbd/nbd-internal.h | 19 -------------------
11
nbd/client.c | 22 +++++++++++++++++++++-
12
3 files changed, 23 insertions(+), 21 deletions(-)
13
14
diff --git a/include/block/nbd.h b/include/block/nbd.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/nbd.h
17
+++ b/include/block/nbd.h
18
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
19
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
20
Error **errp);
21
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
22
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
23
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
24
+ Error **errp);
25
int nbd_client(int fd);
26
int nbd_disconnect(int fd);
27
int nbd_errno_to_system_errno(int err);
28
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/nbd/nbd-internal.h
31
+++ b/nbd/nbd-internal.h
32
@@ -XXX,XX +XXX,XX @@
33
#define NBD_SET_TIMEOUT _IO(0xab, 9)
34
#define NBD_SET_FLAGS _IO(0xab, 10)
35
36
-/* nbd_read_eof
37
- * Tries to read @size bytes from @ioc.
38
- * Returns 1 on success
39
- * 0 on eof, when no data was read (errp is not set)
40
- * negative errno on failure (errp is set)
41
- */
42
-static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
43
- Error **errp)
44
-{
45
- int ret;
46
-
47
- assert(size);
48
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
49
- if (ret < 0) {
50
- ret = -EIO;
51
- }
52
- return ret;
53
-}
54
-
55
/* nbd_write
56
* Writes @size bytes to @ioc. Returns 0 on success.
57
*/
58
diff --git a/nbd/client.c b/nbd/client.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/nbd/client.c
61
+++ b/nbd/client.c
62
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
63
return 0;
64
}
65
66
+/* nbd_read_eof
67
+ * Tries to read @size bytes from @ioc.
68
+ * Returns 1 on success
69
+ * 0 on eof, when no data was read (errp is not set)
70
+ * negative errno on failure (errp is set)
71
+ */
72
+static inline int coroutine_fn
73
+nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
74
+{
75
+ int ret;
76
+
77
+ assert(size);
78
+ ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
79
+ if (ret < 0) {
80
+ ret = -EIO;
81
+ }
82
+ return ret;
83
+}
84
+
85
/* nbd_receive_reply
86
* Returns 1 on success
87
* 0 on eof, when no data was read (errp is not set)
88
* negative errno on failure (errp is set)
89
*/
90
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
91
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
92
+ Error **errp)
93
{
94
int ret;
95
const char *type;
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
Instead of using the convenience wrapper qio_channel_read_all_eof(), use
2
the lower level QIOChannel API. This means duplicating some code, but
3
we'll need this because this coroutine yield is special: We want it to
4
be interruptible so that nbd_client_attach_aio_context() can correctly
5
reenter the coroutine.
6
1
7
This moves the bdrv_dec/inc_in_flight() pair into nbd_read_eof(), so
8
that connection_co will always sit in this exact qio_channel_yield()
9
call when bdrv_drain() returns.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
---
14
include/block/nbd.h | 4 ++--
15
block/nbd-client.c | 8 +-------
16
nbd/client.c | 46 ++++++++++++++++++++++++++++++++++++---------
17
3 files changed, 40 insertions(+), 18 deletions(-)
18
19
diff --git a/include/block/nbd.h b/include/block/nbd.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/nbd.h
22
+++ b/include/block/nbd.h
23
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
24
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
25
Error **errp);
26
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
27
-int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
28
- Error **errp);
29
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
30
+ NBDReply *reply, Error **errp);
31
int nbd_client(int fd);
32
int nbd_disconnect(int fd);
33
int nbd_errno_to_system_errno(int err);
34
diff --git a/block/nbd-client.c b/block/nbd-client.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/nbd-client.c
37
+++ b/block/nbd-client.c
38
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
39
*
40
* Therefore we keep an additional in_flight reference all the time and
41
* only drop it temporarily here.
42
- *
43
- * FIXME This is not safe because the QIOChannel could wake up the
44
- * coroutine for a second time; it is not prepared for coroutine
45
- * resumption from external code.
46
*/
47
- bdrv_dec_in_flight(s->bs);
48
assert(s->reply.handle == 0);
49
- ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
50
- bdrv_inc_in_flight(s->bs);
51
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err);
52
53
if (local_err) {
54
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
55
diff --git a/nbd/client.c b/nbd/client.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/nbd/client.c
58
+++ b/nbd/client.c
59
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
60
* negative errno on failure (errp is set)
61
*/
62
static inline int coroutine_fn
63
-nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
64
+nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
65
+ Error **errp)
66
{
67
- int ret;
68
+ bool partial = false;
69
70
assert(size);
71
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
72
- if (ret < 0) {
73
- ret = -EIO;
74
+ while (size > 0) {
75
+ struct iovec iov = { .iov_base = buffer, .iov_len = size };
76
+ ssize_t len;
77
+
78
+ len = qio_channel_readv(ioc, &iov, 1, errp);
79
+ if (len == QIO_CHANNEL_ERR_BLOCK) {
80
+ bdrv_dec_in_flight(bs);
81
+ qio_channel_yield(ioc, G_IO_IN);
82
+ bdrv_inc_in_flight(bs);
83
+ continue;
84
+ } else if (len < 0) {
85
+ return -EIO;
86
+ } else if (len == 0) {
87
+ if (partial) {
88
+ error_setg(errp,
89
+ "Unexpected end-of-file before all bytes were read");
90
+ return -EIO;
91
+ } else {
92
+ return 0;
93
+ }
94
+ }
95
+
96
+ partial = true;
97
+ size -= len;
98
+ buffer = (uint8_t*) buffer + len;
99
}
100
- return ret;
101
+ return 1;
102
}
103
104
/* nbd_receive_reply
105
+ *
106
+ * Decreases bs->in_flight while waiting for a new reply. This yield is where
107
+ * we wait indefinitely and the coroutine must be able to be safely reentered
108
+ * for nbd_client_attach_aio_context().
109
+ *
110
* Returns 1 on success
111
* 0 on eof, when no data was read (errp is not set)
112
* negative errno on failure (errp is set)
113
*/
114
-int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
115
- Error **errp)
116
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
117
+ NBDReply *reply, Error **errp)
118
{
119
int ret;
120
const char *type;
121
122
- ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
123
+ ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp);
124
if (ret <= 0) {
125
return ret;
126
}
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
Deleted patch
1
bdrv_drain() must not leave connection_co scheduled, so bs->in_flight
2
needs to be increased while the coroutine is waiting to be scheduled
3
in the new AioContext after nbd_client_attach_aio_context().
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
block/nbd-client.c | 20 ++++++++++++++++++--
8
1 file changed, 18 insertions(+), 2 deletions(-)
9
10
diff --git a/block/nbd-client.c b/block/nbd-client.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/nbd-client.c
13
+++ b/block/nbd-client.c
14
@@ -XXX,XX +XXX,XX @@ void nbd_client_detach_aio_context(BlockDriverState *bs)
15
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
16
}
17
18
+static void nbd_client_attach_aio_context_bh(void *opaque)
19
+{
20
+ BlockDriverState *bs = opaque;
21
+ NBDClientSession *client = nbd_get_client_session(bs);
22
+
23
+ /* The node is still drained, so we know the coroutine has yielded in
24
+ * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
25
+ * entered for the first time. Both places are safe for entering the
26
+ * coroutine.*/
27
+ qemu_aio_coroutine_enter(bs->aio_context, client->connection_co);
28
+ bdrv_dec_in_flight(bs);
29
+}
30
+
31
void nbd_client_attach_aio_context(BlockDriverState *bs,
32
AioContext *new_context)
33
{
34
NBDClientSession *client = nbd_get_client_session(bs);
35
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
36
37
- /* FIXME Really need a bdrv_inc_in_flight() here */
38
- aio_co_schedule(new_context, client->connection_co);
39
+ bdrv_inc_in_flight(bs);
40
+
41
+ /* Need to wait here for the BH to run because the BH must run while the
42
+ * node is still drained. */
43
+ aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs);
44
}
45
46
void nbd_client_close(BlockDriverState *bs)
47
--
48
2.20.1
49
50
diff view generated by jsdifflib
Deleted patch
1
The explicit aio_poll() call in bdrv_set_aio_context() was added in
2
commit c2b6428d388 as a workaround for bdrv_drain() failing to achieve
3
to actually quiesce everything (specifically the NBD client code to
4
switch AioContext).
5
1
6
Now that the NBD client has been fixed to complete this operation during
7
bdrv_drain(), we don't need the workaround any more.
8
9
It was wrong anyway: aio_poll() must always be run in the home thread of
10
the AioContext.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
15
block.c | 4 ----
16
1 file changed, 4 deletions(-)
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_set_aio_context(BlockDriverState *bs, AioContext *new_context)
23
bdrv_parent_drained_begin(bs, NULL, false);
24
bdrv_drain(bs); /* ensure there are no in-flight requests */
25
26
- while (aio_poll(ctx, false)) {
27
- /* wait for all bottom halves to execute */
28
- }
29
-
30
bdrv_detach_aio_context(bs);
31
32
/* This function executes in the old AioContext so acquire the new one in
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
4
tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++
5
1 file changed, 32 insertions(+)
6
1
7
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
8
index XXXXXXX..XXXXXXX 100644
9
--- a/tests/test-bdrv-drain.c
10
+++ b/tests/test-bdrv-drain.c
11
@@ -XXX,XX +XXX,XX @@ static void test_append_to_drained(void)
12
blk_unref(blk);
13
}
14
15
+static void test_set_aio_context(void)
16
+{
17
+ BlockDriverState *bs;
18
+ IOThread *a = iothread_new();
19
+ IOThread *b = iothread_new();
20
+ AioContext *ctx_a = iothread_get_aio_context(a);
21
+ AioContext *ctx_b = iothread_get_aio_context(b);
22
+
23
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
24
+ &error_abort);
25
+
26
+ bdrv_drained_begin(bs);
27
+ bdrv_set_aio_context(bs, ctx_a);
28
+
29
+ aio_context_acquire(ctx_a);
30
+ bdrv_drained_end(bs);
31
+
32
+ bdrv_drained_begin(bs);
33
+ bdrv_set_aio_context(bs, ctx_b);
34
+ aio_context_release(ctx_a);
35
+ aio_context_acquire(ctx_b);
36
+ bdrv_set_aio_context(bs, qemu_get_aio_context());
37
+ aio_context_release(ctx_b);
38
+ bdrv_drained_end(bs);
39
+
40
+ bdrv_unref(bs);
41
+ iothread_join(a);
42
+ iothread_join(b);
43
+}
44
+
45
int main(int argc, char **argv)
46
{
47
int ret;
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
49
50
g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
51
52
+ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context);
53
+
54
ret = g_test_run();
55
qemu_event_destroy(&done_event);
56
return ret;
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
Deleted patch
1
aio_poll() has an existing assertion that the function is only called
2
from the AioContext's home thread if blocking is allowed.
3
1
4
This is not enough, some handlers make assumptions about the thread they
5
run in. Extend the assertion to non-blocking calls, too.
6
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
---
10
util/aio-posix.c | 3 ++-
11
1 file changed, 2 insertions(+), 1 deletion(-)
12
13
diff --git a/util/aio-posix.c b/util/aio-posix.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/util/aio-posix.c
16
+++ b/util/aio-posix.c
17
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
18
int64_t timeout;
19
int64_t start = 0;
20
21
+ assert(in_aio_context_home_thread(ctx));
22
+
23
/* aio_notify can avoid the expensive event_notifier_set if
24
* everything (file descriptors, bottom halves, timers) will
25
* be re-evaluated before the next blocking poll(). This is
26
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
27
* so disable the optimization now.
28
*/
29
if (blocking) {
30
- assert(in_aio_context_home_thread(ctx));
31
atomic_add(&ctx->notify_me, 2);
32
}
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
As it already said in the comment, we don't want to create loops in
4
parent->child relations. So, when we try to append @to to @c, we should
5
check that @c is not in @to children subtree, and we should check it
6
recursively, not only the first level. The patch provides BFS-based
7
search, to check the relations.
8
9
This is needed for further fleecing-hook filter usage: we need to
10
append it to source, when the hook is already a parent of target, and
11
source may be in a backing chain of target (fleecing-scheme). So, on
12
appending, the hook should not became a child (direct or through
13
children subtree) of the target.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block.c | 43 +++++++++++++++++++++++++++++++++++++------
19
1 file changed, 37 insertions(+), 6 deletions(-)
20
21
diff --git a/block.c b/block.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block.c
24
+++ b/block.c
25
@@ -XXX,XX +XXX,XX @@ void bdrv_close_all(void)
26
27
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
28
{
29
- BdrvChild *to_c;
30
+ GQueue *queue;
31
+ GHashTable *found;
32
+ bool ret;
33
34
if (c->role->stay_at_node) {
35
return false;
36
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
37
* if A is a child of B, that means we cannot replace A by B there
38
* because that would create a loop. Silently detaching A from B
39
* is also not really an option. So overall just leaving A in
40
- * place there is the most sensible choice. */
41
- QLIST_FOREACH(to_c, &to->children, next) {
42
- if (to_c == c) {
43
- return false;
44
+ * place there is the most sensible choice.
45
+ *
46
+ * We would also create a loop in any cases where @c is only
47
+ * indirectly referenced by @to. Prevent this by returning false
48
+ * if @c is found (by breadth-first search) anywhere in the whole
49
+ * subtree of @to.
50
+ */
51
+
52
+ ret = true;
53
+ found = g_hash_table_new(NULL, NULL);
54
+ g_hash_table_add(found, to);
55
+ queue = g_queue_new();
56
+ g_queue_push_tail(queue, to);
57
+
58
+ while (!g_queue_is_empty(queue)) {
59
+ BlockDriverState *v = g_queue_pop_head(queue);
60
+ BdrvChild *c2;
61
+
62
+ QLIST_FOREACH(c2, &v->children, next) {
63
+ if (c2 == c) {
64
+ ret = false;
65
+ break;
66
+ }
67
+
68
+ if (g_hash_table_contains(found, c2->bs)) {
69
+ continue;
70
+ }
71
+
72
+ g_queue_push_tail(queue, c2->bs);
73
+ g_hash_table_add(found, c2->bs);
74
}
75
}
76
77
- return true;
78
+ g_queue_free(queue);
79
+ g_hash_table_destroy(found);
80
+
81
+ return ret;
82
}
83
84
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
bdrv_check_perm in it's recursion checks each node in context of new
4
permissions for one parent, because of nature of DFS. It works well,
5
while children subgraph of top-most updated node is a tree, i.e. it
6
doesn't have any kind of loops. But if we have a loop (not oriented,
7
of course), i.e. we have two different ways from top-node to some
8
child-node, then bdrv_check_perm will do wrong thing:
9
10
top
11
| \
12
| |
13
v v
14
A B
15
| |
16
v v
17
node
18
19
It will once check new permissions of node in context of new A
20
permissions and old B permissions and once visa-versa. It's a wrong way
21
and may lead to corruption of permission system. We may start with
22
no-permissions and all-shared for both A->node and B->node relations
23
and finish up with non shared write permission for both ways.
24
25
The following commit will add a test, which shows this bug.
26
27
To fix this situation, let's really set BdrvChild permissions during
28
bdrv_check_perm procedure. And we are happy here, as check-perm is
29
already written in transaction manner, so we just need to restore
30
backed-up permissions in _abort.
31
32
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
35
include/block/block_int.h | 5 +++++
36
block.c | 27 ++++++++++++++++++++++++++-
37
2 files changed, 31 insertions(+), 1 deletion(-)
38
39
diff --git a/include/block/block_int.h b/include/block/block_int.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/block/block_int.h
42
+++ b/include/block/block_int.h
43
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
44
*/
45
uint64_t shared_perm;
46
47
+ /* backup of permissions during permission update procedure */
48
+ bool has_backup_perm;
49
+ uint64_t backup_perm;
50
+ uint64_t backup_shared_perm;
51
+
52
QLIST_ENTRY(BdrvChild) next;
53
QLIST_ENTRY(BdrvChild) next_parent;
54
};
55
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
58
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
60
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
61
g_slist_free(ignore_children);
62
63
- return ret;
64
+ if (ret < 0) {
65
+ return ret;
66
+ }
67
+
68
+ if (!c->has_backup_perm) {
69
+ c->has_backup_perm = true;
70
+ c->backup_perm = c->perm;
71
+ c->backup_shared_perm = c->shared_perm;
72
+ }
73
+ /*
74
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
75
+ * same child twice during check_perm procedure
76
+ */
77
+
78
+ c->perm = perm;
79
+ c->shared_perm = shared;
80
+
81
+ return 0;
82
}
83
84
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
85
{
86
uint64_t cumulative_perms, cumulative_shared_perms;
87
88
+ c->has_backup_perm = false;
89
+
90
c->perm = perm;
91
c->shared_perm = shared;
92
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
94
95
static void bdrv_child_abort_perm_update(BdrvChild *c)
96
{
97
+ if (c->has_backup_perm) {
98
+ c->perm = c->backup_perm;
99
+ c->shared_perm = c->backup_shared_perm;
100
+ c->has_backup_perm = false;
101
+ }
102
+
103
bdrv_abort_perm_update(c->bs);
104
}
105
106
--
107
2.20.1
108
109
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add two tests of node graph modification.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/test-bdrv-graph-mod.c | 198 ++++++++++++++++++++++++++++++++++++
9
tests/Makefile.include | 2 +
10
2 files changed, 200 insertions(+)
11
create mode 100644 tests/test-bdrv-graph-mod.c
12
13
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/tests/test-bdrv-graph-mod.c
18
@@ -XXX,XX +XXX,XX @@
19
+/*
20
+ * Block node graph modifications tests
21
+ *
22
+ * Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
23
+ *
24
+ * This program is free software; you can redistribute it and/or modify
25
+ * it under the terms of the GNU General Public License as published by
26
+ * the Free Software Foundation; either version 2 of the License, or
27
+ * (at your option) any later version.
28
+ *
29
+ * This program is distributed in the hope that it will be useful,
30
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+ * GNU General Public License for more details.
33
+ *
34
+ * You should have received a copy of the GNU General Public License
35
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+ *
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "qapi/error.h"
41
+#include "block/block_int.h"
42
+#include "sysemu/block-backend.h"
43
+
44
+static BlockDriver bdrv_pass_through = {
45
+ .format_name = "pass-through",
46
+ .bdrv_child_perm = bdrv_filter_default_perms,
47
+};
48
+
49
+static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
50
+ const BdrvChildRole *role,
51
+ BlockReopenQueue *reopen_queue,
52
+ uint64_t perm, uint64_t shared,
53
+ uint64_t *nperm, uint64_t *nshared)
54
+{
55
+ *nperm = 0;
56
+ *nshared = BLK_PERM_ALL;
57
+}
58
+
59
+static BlockDriver bdrv_no_perm = {
60
+ .format_name = "no-perm",
61
+ .bdrv_child_perm = no_perm_default_perms,
62
+};
63
+
64
+static BlockDriverState *no_perm_node(const char *name)
65
+{
66
+ return bdrv_new_open_driver(&bdrv_no_perm, name, BDRV_O_RDWR, &error_abort);
67
+}
68
+
69
+static BlockDriverState *pass_through_node(const char *name)
70
+{
71
+ return bdrv_new_open_driver(&bdrv_pass_through, name,
72
+ BDRV_O_RDWR, &error_abort);
73
+}
74
+
75
+/*
76
+ * test_update_perm_tree
77
+ *
78
+ * When checking node for a possibility to update permissions, it's subtree
79
+ * should be correctly checked too. New permissions for each node should be
80
+ * calculated and checked in context of permissions of other nodes. If we
81
+ * check new permissions of the node only in context of old permissions of
82
+ * its neighbors, we can finish up with wrong permission graph.
83
+ *
84
+ * This test firstly create the following graph:
85
+ * +--------+
86
+ * | root |
87
+ * +--------+
88
+ * |
89
+ * | perm: write, read
90
+ * | shared: except write
91
+ * v
92
+ * +-------------------+ +----------------+
93
+ * | passtrough filter |---------->| null-co node |
94
+ * +-------------------+ +----------------+
95
+ *
96
+ *
97
+ * and then, tries to append filter under node. Expected behavior: fail.
98
+ * Otherwise we'll get the following picture, with two BdrvChild'ren, having
99
+ * write permission to one node, without actually sharing it.
100
+ *
101
+ * +--------+
102
+ * | root |
103
+ * +--------+
104
+ * |
105
+ * | perm: write, read
106
+ * | shared: except write
107
+ * v
108
+ * +-------------------+
109
+ * | passtrough filter |
110
+ * +-------------------+
111
+ * | |
112
+ * perm: write, read | | perm: write, read
113
+ * shared: except write | | shared: except write
114
+ * v v
115
+ * +----------------+
116
+ * | null co node |
117
+ * +----------------+
118
+ */
119
+static void test_update_perm_tree(void)
120
+{
121
+ Error *local_err = NULL;
122
+
123
+ BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
124
+ BLK_PERM_ALL & ~BLK_PERM_WRITE);
125
+ BlockDriverState *bs = no_perm_node("node");
126
+ BlockDriverState *filter = pass_through_node("filter");
127
+
128
+ blk_insert_bs(root, bs, &error_abort);
129
+
130
+ bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
131
+
132
+ bdrv_append(filter, bs, &local_err);
133
+
134
+ g_assert_nonnull(local_err);
135
+
136
+ bdrv_unref(bs);
137
+ blk_unref(root);
138
+}
139
+
140
+/*
141
+ * test_should_update_child
142
+ *
143
+ * Test that bdrv_replace_node, and concretely should_update_child
144
+ * do the right thing, i.e. not creating loops on the graph.
145
+ *
146
+ * The test does the following:
147
+ * 1. initial graph:
148
+ *
149
+ * +------+ +--------+
150
+ * | root | | filter |
151
+ * +------+ +--------+
152
+ * | |
153
+ * root| target|
154
+ * v v
155
+ * +------+ +--------+
156
+ * | node |<---------| target |
157
+ * +------+ backing +--------+
158
+ *
159
+ * 2. Append @filter above @node. If should_update_child works correctly,
160
+ * it understands, that backing child of @target should not be updated,
161
+ * as it will create a loop on node graph. Resulting picture should
162
+ * be the left one, not the right:
163
+ *
164
+ * +------+ +------+
165
+ * | root | | root |
166
+ * +------+ +------+
167
+ * | |
168
+ * root| root|
169
+ * v v
170
+ * +--------+ target +--------+ target
171
+ * | filter |--------------+ | filter |--------------+
172
+ * +--------+ | +--------+ |
173
+ * | | | ^ v
174
+ * backing| | backing| | +--------+
175
+ * v v | +-----------| target |
176
+ * +------+ +--------+ v backing +--------+
177
+ * | node |<---------| target | +------+
178
+ * +------+ backing +--------+ | node |
179
+ * +------+
180
+ *
181
+ * (good picture) (bad picture)
182
+ *
183
+ */
184
+static void test_should_update_child(void)
185
+{
186
+ BlockBackend *root = blk_new(0, BLK_PERM_ALL);
187
+ BlockDriverState *bs = no_perm_node("node");
188
+ BlockDriverState *filter = no_perm_node("filter");
189
+ BlockDriverState *target = no_perm_node("target");
190
+
191
+ blk_insert_bs(root, bs, &error_abort);
192
+
193
+ bdrv_set_backing_hd(target, bs, &error_abort);
194
+
195
+ g_assert(target->backing->bs == bs);
196
+ bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
197
+ bdrv_append(filter, bs, &error_abort);
198
+ g_assert(target->backing->bs == bs);
199
+
200
+ bdrv_unref(bs);
201
+ blk_unref(root);
202
+}
203
+
204
+int main(int argc, char *argv[])
205
+{
206
+ bdrv_init();
207
+ qemu_init_main_loop(&error_abort);
208
+
209
+ g_test_init(&argc, &argv, NULL);
210
+
211
+ g_test_add_func("/bdrv-graph-mod/update-perm-tree", test_update_perm_tree);
212
+ g_test_add_func("/bdrv-graph-mod/should-update-child",
213
+ test_should_update_child);
214
+
215
+ return g_test_run();
216
+}
217
diff --git a/tests/Makefile.include b/tests/Makefile.include
218
index XXXXXXX..XXXXXXX 100644
219
--- a/tests/Makefile.include
220
+++ b/tests/Makefile.include
221
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-throttle$(EXESUF)
222
check-unit-y += tests/test-thread-pool$(EXESUF)
223
check-unit-y += tests/test-hbitmap$(EXESUF)
224
check-unit-y += tests/test-bdrv-drain$(EXESUF)
225
+check-unit-y += tests/test-bdrv-graph-mod$(EXESUF)
226
check-unit-y += tests/test-blockjob$(EXESUF)
227
check-unit-y += tests/test-blockjob-txn$(EXESUF)
228
check-unit-y += tests/test-block-backend$(EXESUF)
229
@@ -XXX,XX +XXX,XX @@ tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
230
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
231
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
232
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
233
+tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y)
234
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
235
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
236
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
237
--
238
2.20.1
239
240
diff view generated by jsdifflib
Deleted patch
1
From: Thomas Huth <thuth@redhat.com>
2
1
3
The QEMU_PACKED is causing a compiler warning/error with GCC 9:
4
5
CC block/nvme.o
6
block/nvme.c: In function ‘nvme_create_queue_pair’:
7
block/nvme.c:209:22: error: taking address of packed member of
8
‘struct <anonymous>’ may result in an unaligned pointer value
9
[-Werror=address-of-packed-member]
10
209 | q->sq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale];
11
12
All members of the struct are naturally aligned, so there should
13
not be the need for QEMU_PACKED here, and the following QEMU_BUILD_BUG_ON
14
also ensures that there is no padding. Thus simply remove the QEMU_PACKED
15
here.
16
17
Buglink: https://bugs.launchpad.net/qemu/+bug/1817525
18
Reported-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
19
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/nvme.c | 2 +-
24
1 file changed, 1 insertion(+), 1 deletion(-)
25
26
diff --git a/block/nvme.c b/block/nvme.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/nvme.c
29
+++ b/block/nvme.c
30
@@ -XXX,XX +XXX,XX @@ typedef volatile struct {
31
uint8_t reserved1[0xec0];
32
uint8_t cmd_set_specfic[0x100];
33
uint32_t doorbells[];
34
-} QEMU_PACKED NVMeRegs;
35
+} NVMeRegs;
36
37
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
38
39
--
40
2.20.1
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
bdrv_refresh_filename() should invoke itself recursively on all
4
children, not just on file.
5
6
With that change, we can remove the manual invocations in blkverify,
7
quorum, commit, mirror, and blklogwrites.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20190201192935.18394-3-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block.c | 9 +++++----
16
block/blklogwrites.c | 3 ---
17
block/blkverify.c | 3 ---
18
block/commit.c | 1 -
19
block/mirror.c | 1 -
20
block/quorum.c | 1 -
21
6 files changed, 5 insertions(+), 13 deletions(-)
22
23
diff --git a/block.c b/block.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
26
+++ b/block.c
27
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
28
void bdrv_refresh_filename(BlockDriverState *bs)
29
{
30
BlockDriver *drv = bs->drv;
31
+ BdrvChild *child;
32
QDict *opts;
33
34
if (!drv) {
35
return;
36
}
37
38
- /* This BDS's file name will most probably depend on its file's name, so
39
- * refresh that first */
40
- if (bs->file) {
41
- bdrv_refresh_filename(bs->file->bs);
42
+ /* This BDS's file name may depend on any of its children's file names, so
43
+ * refresh those first */
44
+ QLIST_FOREACH(child, &bs->children, next) {
45
+ bdrv_refresh_filename(child->bs);
46
}
47
48
if (drv->bdrv_refresh_filename) {
49
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/blklogwrites.c
52
+++ b/block/blklogwrites.c
53
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_filename(BlockDriverState *bs,
54
{
55
BDRVBlkLogWritesState *s = bs->opaque;
56
57
- /* bs->file->bs has already been refreshed */
58
- bdrv_refresh_filename(s->log_file->bs);
59
-
60
if (bs->file->bs->full_open_options
61
&& s->log_file->bs->full_open_options)
62
{
63
diff --git a/block/blkverify.c b/block/blkverify.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/blkverify.c
66
+++ b/block/blkverify.c
67
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
68
{
69
BDRVBlkverifyState *s = bs->opaque;
70
71
- /* bs->file->bs has already been refreshed */
72
- bdrv_refresh_filename(s->test_file->bs);
73
-
74
if (bs->file->bs->full_open_options
75
&& s->test_file->bs->full_open_options)
76
{
77
diff --git a/block/commit.c b/block/commit.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/commit.c
80
+++ b/block/commit.c
81
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
82
83
static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
84
{
85
- bdrv_refresh_filename(bs->backing->bs);
86
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
87
bs->backing->bs->filename);
88
}
89
diff --git a/block/mirror.c b/block/mirror.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/mirror.c
92
+++ b/block/mirror.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
94
* bdrv_set_backing_hd */
95
return;
96
}
97
- bdrv_refresh_filename(bs->backing->bs);
98
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
99
bs->backing->bs->filename);
100
}
101
diff --git a/block/quorum.c b/block/quorum.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/block/quorum.c
104
+++ b/block/quorum.c
105
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
106
int i;
107
108
for (i = 0; i < s->num_children; i++) {
109
- bdrv_refresh_filename(s->children[i]->bs);
110
if (!s->children[i]->bs->full_open_options) {
111
return;
112
}
113
--
114
2.20.1
115
116
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
bdrv_refresh_filename() should simply skip all implicit nodes. They are
4
supposed to be invisible to the user, so they should not appear in
5
filename information.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-4-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block.c | 14 ++++++++++++++
14
1 file changed, 14 insertions(+)
15
16
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
21
bdrv_refresh_filename(child->bs);
22
}
23
24
+ if (bs->implicit) {
25
+ /* For implicit nodes, just copy everything from the single child */
26
+ child = QLIST_FIRST(&bs->children);
27
+ assert(QLIST_NEXT(child, next) == NULL);
28
+
29
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
30
+ child->bs->exact_filename);
31
+ pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
32
+
33
+ bs->full_open_options = qobject_ref(child->bs->full_open_options);
34
+
35
+ return;
36
+ }
37
+
38
if (drv->bdrv_refresh_filename) {
39
/* Obsolete information is of no use here, so drop the old file name
40
* information before refreshing it */
41
--
42
2.20.1
43
44
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Basically, bdrv_refresh_filename() should respect all children of a
4
BlockDriverState. However, generally those children are driver-specific,
5
so this function cannot handle the general case. On the other hand,
6
there are only few drivers which use other children than @file and
7
@backing (that being vmdk, quorum, and blkverify).
8
9
Most block drivers only use @file and/or @backing (if they use any
10
children at all). Both can be implemented directly in
11
bdrv_refresh_filename.
12
13
The user overriding the file's filename is already handled, however, the
14
user overriding the backing file is not. If this is done, opening the
15
BDS with the plain filename of its file will not be correct, so we may
16
not set bs->exact_filename in that case.
17
18
iotest 051 contains test cases for overriding the backing file, and so
19
its output changes with this patch applied.
20
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
23
Message-id: 20190201192935.18394-6-mreitz@redhat.com
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
block.c | 38 ++++++++++++++++++++++++++++++++++-
27
tests/qemu-iotests/051.out | 8 ++++----
28
tests/qemu-iotests/051.pc.out | 8 ++++----
29
3 files changed, 45 insertions(+), 9 deletions(-)
30
31
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
34
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
36
return found_any;
37
}
38
39
+/* Note: This function may return false positives; it may return true
40
+ * even if opening the backing file specified by bs's image header
41
+ * would result in exactly bs->backing. */
42
+static bool bdrv_backing_overridden(BlockDriverState *bs)
43
+{
44
+ if (bs->backing) {
45
+ return strcmp(bs->auto_backing_file,
46
+ bs->backing->bs->filename);
47
+ } else {
48
+ /* No backing BDS, so if the image header reports any backing
49
+ * file, it must have been suppressed */
50
+ return bs->auto_backing_file[0] != '\0';
51
+ }
52
+}
53
+
54
/* Updates the following BDS fields:
55
* - exact_filename: A filename which may be used for opening a block device
56
* which (mostly) equals the given BDS (even without any
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
58
BlockDriver *drv = bs->drv;
59
BdrvChild *child;
60
QDict *opts;
61
+ bool backing_overridden;
62
63
if (!drv) {
64
return;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
66
return;
67
}
68
69
+ backing_overridden = bdrv_backing_overridden(bs);
70
+
71
+ if (bs->open_flags & BDRV_O_NO_IO) {
72
+ /* Without I/O, the backing file does not change anything.
73
+ * Therefore, in such a case (primarily qemu-img), we can
74
+ * pretend the backing file has not been overridden even if
75
+ * it technically has been. */
76
+ backing_overridden = false;
77
+ }
78
+
79
if (drv->bdrv_refresh_filename) {
80
/* Obsolete information is of no use here, so drop the old file name
81
* information before refreshing it */
82
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
83
84
opts = qdict_new();
85
has_open_options = append_open_options(opts, bs);
86
+ has_open_options |= backing_overridden;
87
88
/* If no specific options have been given for this BDS, the filename of
89
* the underlying file should suffice for this one as well */
90
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
91
* file BDS. The full options QDict of that file BDS should somehow
92
* contain a representation of the filename, therefore the following
93
* suffices without querying the (exact_)filename of this BDS. */
94
- if (bs->file->bs->full_open_options) {
95
+ if (bs->file->bs->full_open_options &&
96
+ (!bs->backing || bs->backing->bs->full_open_options))
97
+ {
98
qdict_put_str(opts, "driver", drv->format_name);
99
qdict_put(opts, "file",
100
qobject_ref(bs->file->bs->full_open_options));
101
102
+ if (bs->backing) {
103
+ qdict_put(opts, "backing",
104
+ qobject_ref(bs->backing->bs->full_open_options));
105
+ } else if (backing_overridden) {
106
+ qdict_put_null(opts, "backing");
107
+ }
108
+
109
bs->full_open_options = opts;
110
} else {
111
qobject_unref(opts);
112
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/qemu-iotests/051.out
115
+++ b/tests/qemu-iotests/051.out
116
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
117
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
118
QEMU X.Y.Z monitor - type 'help' for more information
119
(qemu) info block
120
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
121
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
122
Removable device: not locked, tray closed
123
Cache mode: writeback
124
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
125
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
126
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
127
QEMU X.Y.Z monitor - type 'help' for more information
128
(qemu) info block
129
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
130
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
131
Removable device: not locked, tray closed
132
Cache mode: writeback
133
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
134
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
135
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
136
QEMU X.Y.Z monitor - type 'help' for more information
137
(qemu) info block
138
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
139
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
140
Removable device: not locked, tray closed
141
Cache mode: writethrough
142
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
143
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
144
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
145
QEMU X.Y.Z monitor - type 'help' for more information
146
(qemu) info block
147
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
148
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
149
Removable device: not locked, tray closed
150
Cache mode: writeback, ignore flushes
151
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
152
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
153
index XXXXXXX..XXXXXXX 100644
154
--- a/tests/qemu-iotests/051.pc.out
155
+++ b/tests/qemu-iotests/051.pc.out
156
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
157
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
158
QEMU X.Y.Z monitor - type 'help' for more information
159
(qemu) info block
160
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
161
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
162
Removable device: not locked, tray closed
163
Cache mode: writeback
164
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
165
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
166
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
167
QEMU X.Y.Z monitor - type 'help' for more information
168
(qemu) info block
169
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
170
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
171
Removable device: not locked, tray closed
172
Cache mode: writeback
173
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
174
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
175
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
176
QEMU X.Y.Z monitor - type 'help' for more information
177
(qemu) info block
178
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
179
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
180
Removable device: not locked, tray closed
181
Cache mode: writethrough
182
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
183
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
184
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
185
QEMU X.Y.Z monitor - type 'help' for more information
186
(qemu) info block
187
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
188
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
189
Removable device: not locked, tray closed
190
Cache mode: writeback, ignore flushes
191
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
192
--
193
2.20.1
194
195
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This function queries a node; since we cannot do that right now, it
4
executes query-named-block-nodes and returns the matching node's object.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-id: 20190201192935.18394-8-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 7 +++++++
14
1 file changed, 7 insertions(+)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
21
else:
22
iotests.log(ev)
23
24
+ def node_info(self, node_name):
25
+ nodes = self.qmp('query-named-block-nodes')
26
+ for x in nodes['return']:
27
+ if x['node-name'] == node_name:
28
+ return x
29
+ return None
30
+
31
32
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-9-mreitz@redhat.com
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/qemu-iotests/228 | 242 +++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/228.out | 84 +++++++++++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 327 insertions(+)
11
create mode 100755 tests/qemu-iotests/228
12
create mode 100644 tests/qemu-iotests/228.out
13
14
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/228
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python
21
+#
22
+# Test for when a backing file is considered overridden (thus, a
23
+# json:{} filename is generated for the overlay) and when it is not
24
+#
25
+# Copyright (C) 2018 Red Hat, Inc.
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
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
41
+
42
+import iotests
43
+from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
44
+ filter_qmp_testfiles, filter_qmp_imgfmt
45
+
46
+# Need backing file and change-backing-file support
47
+iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
48
+iotests.verify_platform(['linux'])
49
+
50
+
51
+def log_node_info(node):
52
+ log('')
53
+
54
+ log('bs->filename: ' + node['image']['filename'],
55
+ filters=[filter_testfiles, filter_imgfmt])
56
+ log('bs->backing_file: ' + node['backing_file'],
57
+ filters=[filter_testfiles, filter_imgfmt])
58
+
59
+ if 'backing-image' in node['image']:
60
+ log('bs->backing->bs->filename: ' +
61
+ node['image']['backing-image']['filename'],
62
+ filters=[filter_testfiles, filter_imgfmt])
63
+ else:
64
+ log('bs->backing: (none)')
65
+
66
+ log('')
67
+
68
+
69
+with iotests.FilePath('base.img') as base_img_path, \
70
+ iotests.FilePath('top.img') as top_img_path, \
71
+ iotests.VM() as vm:
72
+
73
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
74
+ # Choose a funny way to describe the backing filename
75
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b',
76
+ 'file:' + base_img_path, top_img_path) == 0
77
+
78
+ vm.launch()
79
+
80
+ log('--- Implicit backing file ---')
81
+ log('')
82
+
83
+ vm.qmp_log('blockdev-add',
84
+ node_name='node0',
85
+ driver=iotests.imgfmt,
86
+ file={
87
+ 'driver': 'file',
88
+ 'filename': top_img_path
89
+ },
90
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
91
+
92
+ # Filename should be plain, and the backing filename should not
93
+ # contain the "file:" prefix
94
+ log_node_info(vm.node_info('node0'))
95
+
96
+ vm.qmp_log('blockdev-del', node_name='node0')
97
+
98
+ log('')
99
+ log('--- change-backing-file ---')
100
+ log('')
101
+
102
+ vm.qmp_log('blockdev-add',
103
+ node_name='node0',
104
+ driver=iotests.imgfmt,
105
+ file={
106
+ 'driver': 'file',
107
+ 'filename': top_img_path
108
+ },
109
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
110
+
111
+ # Changing the backing file to a qemu-reported filename should
112
+ # result in qemu accepting the corresponding BDS as the implicit
113
+ # backing BDS (and thus not generate a json:{} filename).
114
+ # So, first, query the backing filename.
115
+
116
+ backing_filename = \
117
+ vm.node_info('node0')['image']['backing-image']['filename']
118
+
119
+ # Next, change the backing file to something different
120
+
121
+ vm.qmp_log('change-backing-file',
122
+ image_node_name='node0',
123
+ device='node0',
124
+ backing_file='null-co://',
125
+ filters=[filter_qmp_testfiles])
126
+
127
+ # Now, verify that we get a json:{} filename
128
+ # (Image header says "null-co://", actual backing file still is
129
+ # base_img_path)
130
+
131
+ log_node_info(vm.node_info('node0'))
132
+
133
+ # Change it back
134
+ # (To get header and backing file in sync)
135
+
136
+ vm.qmp_log('change-backing-file',
137
+ image_node_name='node0',
138
+ device='node0',
139
+ backing_file=backing_filename,
140
+ filters=[filter_qmp_testfiles])
141
+
142
+ # And verify that we get our original results
143
+
144
+ log_node_info(vm.node_info('node0'))
145
+
146
+ # Finally, try a "file:" prefix. While this is actually what we
147
+ # originally had in the image header, qemu will not reopen the
148
+ # backing file here, so it cannot verify that this filename
149
+ # "resolves" to the actual backing BDS's filename and will thus
150
+ # consider both to be different.
151
+ # (This may be fixed in the future.)
152
+
153
+ vm.qmp_log('change-backing-file',
154
+ image_node_name='node0',
155
+ device='node0',
156
+ backing_file=('file:' + backing_filename),
157
+ filters=[filter_qmp_testfiles])
158
+
159
+ # So now we should get a json:{} filename
160
+
161
+ log_node_info(vm.node_info('node0'))
162
+
163
+ # Remove and re-attach so we can see that (as in our first try),
164
+ # opening the image anew helps qemu resolve the header backing
165
+ # filename.
166
+
167
+ vm.qmp_log('blockdev-del', node_name='node0')
168
+
169
+ vm.qmp_log('blockdev-add',
170
+ node_name='node0',
171
+ driver=iotests.imgfmt,
172
+ file={
173
+ 'driver': 'file',
174
+ 'filename': top_img_path
175
+ },
176
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
177
+
178
+ log_node_info(vm.node_info('node0'))
179
+
180
+ vm.qmp_log('blockdev-del', node_name='node0')
181
+
182
+ log('')
183
+ log('--- Override backing file ---')
184
+ log('')
185
+
186
+ # For this test, we need the plain filename in the image header
187
+ # (because qemu cannot "canonicalize"/"resolve" the backing
188
+ # filename unless the backing file is opened implicitly with the
189
+ # overlay)
190
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
191
+ top_img_path) == 0
192
+
193
+ # You can only reliably override backing options by using a node
194
+ # reference (or by specifying file.filename, but, well...)
195
+ vm.qmp_log('blockdev-add', node_name='null', driver='null-co')
196
+
197
+ vm.qmp_log('blockdev-add',
198
+ node_name='node0',
199
+ driver=iotests.imgfmt,
200
+ file={
201
+ 'driver': 'file',
202
+ 'filename': top_img_path
203
+ },
204
+ backing='null',
205
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
206
+
207
+ # Should get a json:{} filename (and bs->backing_file is
208
+ # null-co://, because that field actually has not much to do
209
+ # with the header backing filename (except that it is changed by
210
+ # change-backing-file))
211
+
212
+ log_node_info(vm.node_info('node0'))
213
+
214
+ # Detach the backing file by reopening the whole thing
215
+
216
+ vm.qmp_log('blockdev-del', node_name='node0')
217
+ vm.qmp_log('blockdev-del', node_name='null')
218
+
219
+ vm.qmp_log('blockdev-add',
220
+ node_name='node0',
221
+ driver=iotests.imgfmt,
222
+ file={
223
+ 'driver': 'file',
224
+ 'filename': top_img_path
225
+ },
226
+ backing=None,
227
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
228
+
229
+ # Should get a json:{} filename (because we overrode the backing
230
+ # file to not be there)
231
+
232
+ log_node_info(vm.node_info('node0'))
233
+
234
+ # Open the original backing file
235
+
236
+ vm.qmp_log('blockdev-add',
237
+ node_name='original-backing',
238
+ driver=iotests.imgfmt,
239
+ file={
240
+ 'driver': 'file',
241
+ 'filename': base_img_path
242
+ },
243
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
244
+
245
+ # Attach the original backing file to its overlay
246
+
247
+ vm.qmp_log('blockdev-snapshot',
248
+ node='original-backing',
249
+ overlay='node0')
250
+
251
+ # This should give us the original plain result
252
+ # FIXME: Currently, the block layer considers the runtime backing
253
+ # file to be different from the image header, which is
254
+ # wrong. This is fixed by a future patch.
255
+
256
+ log_node_info(vm.node_info('node0'))
257
+
258
+ vm.qmp_log('blockdev-del', node_name='node0')
259
+ vm.qmp_log('blockdev-del', node_name='original-backing')
260
+
261
+ vm.shutdown()
262
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
263
new file mode 100644
264
index XXXXXXX..XXXXXXX
265
--- /dev/null
266
+++ b/tests/qemu-iotests/228.out
267
@@ -XXX,XX +XXX,XX @@
268
+--- Implicit backing file ---
269
+
270
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
271
+{"return": {}}
272
+
273
+bs->filename: TEST_DIR/PID-top.img
274
+bs->backing_file: TEST_DIR/PID-base.img
275
+bs->backing->bs->filename: TEST_DIR/PID-base.img
276
+
277
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
278
+{"return": {}}
279
+
280
+--- change-backing-file ---
281
+
282
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
283
+{"return": {}}
284
+{"execute": "change-backing-file", "arguments": {"backing-file": "null-co://", "device": "node0", "image-node-name": "node0"}}
285
+{"return": {}}
286
+
287
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
288
+bs->backing_file: null-co://
289
+bs->backing->bs->filename: TEST_DIR/PID-base.img
290
+
291
+{"execute": "change-backing-file", "arguments": {"backing-file": "TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
292
+{"return": {}}
293
+
294
+bs->filename: TEST_DIR/PID-top.img
295
+bs->backing_file: TEST_DIR/PID-base.img
296
+bs->backing->bs->filename: TEST_DIR/PID-base.img
297
+
298
+{"execute": "change-backing-file", "arguments": {"backing-file": "file:TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
299
+{"return": {}}
300
+
301
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
302
+bs->backing_file: file:TEST_DIR/PID-base.img
303
+bs->backing->bs->filename: TEST_DIR/PID-base.img
304
+
305
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
306
+{"return": {}}
307
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
308
+{"return": {}}
309
+
310
+bs->filename: TEST_DIR/PID-top.img
311
+bs->backing_file: TEST_DIR/PID-base.img
312
+bs->backing->bs->filename: TEST_DIR/PID-base.img
313
+
314
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
315
+{"return": {}}
316
+
317
+--- Override backing file ---
318
+
319
+{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "null"}}
320
+{"return": {}}
321
+{"execute": "blockdev-add", "arguments": {"backing": "null", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
322
+{"return": {}}
323
+
324
+bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
325
+bs->backing_file: null-co://
326
+bs->backing->bs->filename: null-co://
327
+
328
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
329
+{"return": {}}
330
+{"execute": "blockdev-del", "arguments": {"node-name": "null"}}
331
+{"return": {}}
332
+{"execute": "blockdev-add", "arguments": {"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
333
+{"return": {}}
334
+
335
+bs->filename: json:{"backing": null, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
336
+bs->backing_file: TEST_DIR/PID-base.img
337
+bs->backing: (none)
338
+
339
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "original-backing"}}
340
+{"return": {}}
341
+{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
342
+{"return": {}}
343
+
344
+bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
345
+bs->backing_file: TEST_DIR/PID-base.img
346
+bs->backing->bs->filename: TEST_DIR/PID-base.img
347
+
348
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
349
+{"return": {}}
350
+{"execute": "blockdev-del", "arguments": {"node-name": "original-backing"}}
351
+{"return": {}}
352
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
353
index XXXXXXX..XXXXXXX 100644
354
--- a/tests/qemu-iotests/group
355
+++ b/tests/qemu-iotests/group
356
@@ -XXX,XX +XXX,XX @@
357
225 rw auto quick
358
226 auto quick
359
227 auto quick
360
+228 rw auto quick
361
229 auto quick
362
231 auto quick
363
232 auto quick
364
--
365
2.20.1
366
367
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Besides being safe for arbitrary path lengths, after some follow-up
4
patches all callers will want a freshly allocated buffer anyway.
5
6
In the meantime, path_combine_deprecated() is added which has the same
7
interface as path_combine() had before this patch. All callers to that
8
function will be converted in follow-up patches.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-id: 20190201192935.18394-10-mreitz@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
include/block/block.h | 4 +-
17
block.c | 85 ++++++++++++++++++++++++-------------------
18
block/vmdk.c | 3 +-
19
3 files changed, 49 insertions(+), 43 deletions(-)
20
21
diff --git a/include/block/block.h b/include/block/block.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block.h
24
+++ b/include/block/block.h
25
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
26
27
int path_has_protocol(const char *path);
28
int path_is_absolute(const char *path);
29
-void path_combine(char *dest, int dest_size,
30
- const char *base_path,
31
- const char *filename);
32
+char *path_combine(const char *base_path, const char *filename);
33
34
int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
35
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
36
diff --git a/block.c b/block.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block.c
39
+++ b/block.c
40
@@ -XXX,XX +XXX,XX @@ int path_is_absolute(const char *path)
41
#endif
42
}
43
44
-/* if filename is absolute, just copy it to dest. Otherwise, build a
45
+/* if filename is absolute, just return its duplicate. Otherwise, build a
46
path to it by considering it is relative to base_path. URL are
47
supported. */
48
-void path_combine(char *dest, int dest_size,
49
- const char *base_path,
50
- const char *filename)
51
+char *path_combine(const char *base_path, const char *filename)
52
{
53
+ const char *protocol_stripped = NULL;
54
const char *p, *p1;
55
+ char *result;
56
int len;
57
58
- if (dest_size <= 0)
59
- return;
60
if (path_is_absolute(filename)) {
61
- pstrcpy(dest, dest_size, filename);
62
- } else {
63
- const char *protocol_stripped = NULL;
64
+ return g_strdup(filename);
65
+ }
66
67
- if (path_has_protocol(base_path)) {
68
- protocol_stripped = strchr(base_path, ':');
69
- if (protocol_stripped) {
70
- protocol_stripped++;
71
- }
72
+ if (path_has_protocol(base_path)) {
73
+ protocol_stripped = strchr(base_path, ':');
74
+ if (protocol_stripped) {
75
+ protocol_stripped++;
76
}
77
- p = protocol_stripped ?: base_path;
78
+ }
79
+ p = protocol_stripped ?: base_path;
80
81
- p1 = strrchr(base_path, '/');
82
+ p1 = strrchr(base_path, '/');
83
#ifdef _WIN32
84
- {
85
- const char *p2;
86
- p2 = strrchr(base_path, '\\');
87
- if (!p1 || p2 > p1)
88
- p1 = p2;
89
+ {
90
+ const char *p2;
91
+ p2 = strrchr(base_path, '\\');
92
+ if (!p1 || p2 > p1) {
93
+ p1 = p2;
94
}
95
+ }
96
#endif
97
- if (p1)
98
- p1++;
99
- else
100
- p1 = base_path;
101
- if (p1 > p)
102
- p = p1;
103
- len = p - base_path;
104
- if (len > dest_size - 1)
105
- len = dest_size - 1;
106
- memcpy(dest, base_path, len);
107
- dest[len] = '\0';
108
- pstrcat(dest, dest_size, filename);
109
+ if (p1) {
110
+ p1++;
111
+ } else {
112
+ p1 = base_path;
113
+ }
114
+ if (p1 > p) {
115
+ p = p1;
116
}
117
+ len = p - base_path;
118
+
119
+ result = g_malloc(len + strlen(filename) + 1);
120
+ memcpy(result, base_path, len);
121
+ strcpy(result + len, filename);
122
+
123
+ return result;
124
+}
125
+
126
+static void path_combine_deprecated(char *dest, int dest_size,
127
+ const char *base_path,
128
+ const char *filename)
129
+{
130
+ char *combined = path_combine(base_path, filename);
131
+ pstrcpy(dest, dest_size, combined);
132
+ g_free(combined);
133
}
134
135
/*
136
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
137
error_setg(errp, "Cannot use relative backing file names for '%s'",
138
backed);
139
} else {
140
- path_combine(dest, sz, backed, backing);
141
+ path_combine_deprecated(dest, sz, backed, backing);
142
}
143
}
144
145
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
146
} else {
147
/* If not an absolute filename path, make it relative to the current
148
* image's filename path */
149
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
150
- backing_file);
151
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
152
+ backing_file);
153
154
/* We are going to compare absolute pathnames */
155
if (!realpath(filename_tmp, filename_full)) {
156
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
157
158
/* We need to make sure the backing filename we are comparing against
159
* is relative to the current image filename (or absolute) */
160
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
161
- curr_bs->backing_file);
162
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
163
+ curr_bs->backing_file);
164
165
if (!realpath(filename_tmp, backing_file_full)) {
166
continue;
167
diff --git a/block/vmdk.c b/block/vmdk.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/block/vmdk.c
170
+++ b/block/vmdk.c
171
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
172
return -EINVAL;
173
}
174
175
- extent_path = g_malloc0(PATH_MAX);
176
- path_combine(extent_path, PATH_MAX, desc_file_path, fname);
177
+ extent_path = path_combine(desc_file_path, fname);
178
179
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
180
assert(ret < 32);
181
--
182
2.20.1
183
184
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Make bdrv_get_full_backing_filename() return an allocated string instead
4
of placing the result in a caller-provided buffer.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Message-id: 20190201192935.18394-12-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
include/block/block.h | 3 +--
12
block.c | 48 +++++++++++++++----------------------------
13
block/qapi.c | 12 ++---------
14
3 files changed, 20 insertions(+), 43 deletions(-)
15
16
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
19
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
21
22
void bdrv_get_backing_filename(BlockDriverState *bs,
23
char *filename, int filename_size);
24
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
25
- char *dest, size_t sz, Error **errp);
26
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
27
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
28
const char *backing,
29
Error **errp);
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
35
}
36
}
37
38
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
39
- Error **errp)
40
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
41
{
42
char *backed;
43
- char *full_name;
44
- Error *local_error = NULL;
45
46
bdrv_refresh_filename(bs);
47
48
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
49
-
50
- full_name = bdrv_get_full_backing_filename_from_filename(backed,
51
- bs->backing_file,
52
- &local_error);
53
- if (full_name) {
54
- pstrcpy(dest, sz, full_name);
55
- g_free(full_name);
56
- } else if (local_error) {
57
- error_propagate(errp, local_error);
58
- } else if (sz > 0) {
59
- *dest = '\0';
60
- }
61
+ return bdrv_get_full_backing_filename_from_filename(backed,
62
+ bs->backing_file,
63
+ errp);
64
}
65
66
void bdrv_register(BlockDriver *bdrv)
67
@@ -XXX,XX +XXX,XX @@ out:
68
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
69
const char *bdref_key, Error **errp)
70
{
71
- char *backing_filename = g_malloc0(PATH_MAX);
72
+ char *backing_filename = NULL;
73
char *bdref_key_dot;
74
const char *reference = NULL;
75
int ret = 0;
76
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
77
*/
78
reference = qdict_get_try_str(parent_options, bdref_key);
79
if (reference || qdict_haskey(options, "file.filename")) {
80
- backing_filename[0] = '\0';
81
+ /* keep backing_filename NULL */
82
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
83
qobject_unref(options);
84
goto free_exit;
85
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
86
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
87
}
88
89
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
90
- &local_err);
91
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
92
if (local_err) {
93
ret = -EINVAL;
94
error_propagate(errp, local_err);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
96
qdict_put_str(options, "driver", bs->backing_format);
97
}
98
99
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
100
- reference, options, 0, bs, &child_backing,
101
- errp);
102
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
103
+ &child_backing, errp);
104
if (!backing_hd) {
105
bs->open_flags |= BDRV_O_NO_BACKING;
106
error_prepend(errp, "Could not open backing file: ");
107
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
108
int is_protocol = 0;
109
BlockDriverState *curr_bs = NULL;
110
BlockDriverState *retval = NULL;
111
- Error *local_error = NULL;
112
113
if (!bs || !bs->drv || !backing_file) {
114
return NULL;
115
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
116
/* If either of the filename paths is actually a protocol, then
117
* compare unmodified paths; otherwise make paths relative */
118
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
119
+ char *backing_file_full_ret;
120
+
121
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
122
retval = curr_bs->backing->bs;
123
break;
124
}
125
/* Also check against the full backing filename for the image */
126
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
127
- &local_error);
128
- if (local_error == NULL) {
129
- if (strcmp(backing_file, backing_file_full) == 0) {
130
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
131
+ NULL);
132
+ if (backing_file_full_ret) {
133
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
134
+ g_free(backing_file_full_ret);
135
+ if (equal) {
136
retval = curr_bs->backing->bs;
137
break;
138
}
139
- } else {
140
- error_free(local_error);
141
- local_error = NULL;
142
}
143
} else {
144
/* If not an absolute filename path, make it relative to the current
145
diff --git a/block/qapi.c b/block/qapi.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/block/qapi.c
148
+++ b/block/qapi.c
149
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
150
151
backing_filename = bs->backing_file;
152
if (backing_filename[0] != '\0') {
153
- char *backing_filename2 = g_malloc0(PATH_MAX);
154
+ char *backing_filename2;
155
info->backing_filename = g_strdup(backing_filename);
156
info->has_backing_filename = true;
157
- bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
158
- if (err) {
159
- /* Can't reconstruct the full backing filename, so we must omit
160
- * this field and apply a Best Effort to this query. */
161
- g_free(backing_filename2);
162
- backing_filename2 = NULL;
163
- error_free(err);
164
- err = NULL;
165
- }
166
+ backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
167
168
/* Always report the full_backing_filename if present, even if it's the
169
* same as backing_filename. That they are same is useful info. */
170
--
171
2.20.1
172
173
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This is a general function for making a filename that is relative to a
4
certain BDS absolute.
5
6
It calls bdrv_get_full_backing_filename_from_filename() for now, but
7
that will be changed in a follow-up patch.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-13-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block.c | 27 ++++++++++++++++++++-------
15
1 file changed, 20 insertions(+), 7 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
22
}
23
}
24
25
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
26
+/*
27
+ * If @filename is empty or NULL, this function returns NULL without
28
+ * setting @errp. In all other cases, NULL will only be returned with
29
+ * @errp set.
30
+ */
31
+static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
32
+ const char *filename, Error **errp)
33
{
34
- char *backed;
35
+ char *bs_filename;
36
37
- bdrv_refresh_filename(bs);
38
+ bdrv_refresh_filename(relative_to);
39
+
40
+ bs_filename = relative_to->exact_filename[0]
41
+ ? relative_to->exact_filename
42
+ : relative_to->filename;
43
44
- backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
45
- return bdrv_get_full_backing_filename_from_filename(backed,
46
- bs->backing_file,
47
- errp);
48
+ return bdrv_get_full_backing_filename_from_filename(bs_filename,
49
+ filename ?: "", errp);
50
+}
51
+
52
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
53
+{
54
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
55
}
56
57
void bdrv_register(BlockDriver *bdrv)
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
bdrv_find_backing_image() should use bdrv_get_full_backing_filename() or
4
bdrv_make_absolute_filename() instead of trying to do what those
5
functions do by itself.
6
7
path_combine_deprecated() can now be dropped, so let's do that.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-14-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block.c | 33 ++++++++++-----------------------
15
1 file changed, 10 insertions(+), 23 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *path_combine(const char *base_path, const char *filename)
22
return result;
23
}
24
25
-static void path_combine_deprecated(char *dest, int dest_size,
26
- const char *base_path,
27
- const char *filename)
28
-{
29
- char *combined = path_combine(base_path, filename);
30
- pstrcpy(dest, dest_size, combined);
31
- g_free(combined);
32
-}
33
-
34
/*
35
* Helper function for bdrv_parse_filename() implementations to remove optional
36
* protocol prefixes (especially "file:") from a filename and for putting the
37
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
38
39
filename_full = g_malloc(PATH_MAX);
40
backing_file_full = g_malloc(PATH_MAX);
41
- filename_tmp = g_malloc(PATH_MAX);
42
43
is_protocol = path_has_protocol(backing_file);
44
45
- /* This will recursively refresh everything in the backing chain */
46
- bdrv_refresh_filename(bs);
47
-
48
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
49
50
/* If either of the filename paths is actually a protocol, then
51
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
52
} else {
53
/* If not an absolute filename path, make it relative to the current
54
* image's filename path */
55
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
56
- backing_file);
57
-
58
- /* We are going to compare absolute pathnames */
59
- if (!realpath(filename_tmp, filename_full)) {
60
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
61
+ NULL);
62
+ /* We are going to compare canonicalized absolute pathnames */
63
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
64
+ g_free(filename_tmp);
65
continue;
66
}
67
+ g_free(filename_tmp);
68
69
/* We need to make sure the backing filename we are comparing against
70
* is relative to the current image filename (or absolute) */
71
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
72
- curr_bs->backing_file);
73
-
74
- if (!realpath(filename_tmp, backing_file_full)) {
75
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
76
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
77
+ g_free(filename_tmp);
78
continue;
79
}
80
+ g_free(filename_tmp);
81
82
if (strcmp(backing_file_full, filename_full) == 0) {
83
retval = curr_bs->backing->bs;
84
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
85
86
g_free(filename_full);
87
g_free(backing_file_full);
88
- g_free(filename_tmp);
89
return retval;
90
}
91
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This function may be implemented by block drivers to derive a directory
4
name from a BDS. Concatenating this g_free()-able string with a relative
5
filename must result in a valid (not necessarily existing) filename, so
6
this is a function that should generally be not implemented by format
7
drivers, because this is protocol-specific.
8
9
If a BDS's driver does not implement this function, bdrv_dirname() will
10
fall through to the BDS's file if it exists. If it does not, the
11
exact_filename field will be used to generate a directory name.
12
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Message-id: 20190201192935.18394-15-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
include/block/block.h | 1 +
19
include/block/block_int.h | 7 +++++++
20
block.c | 27 +++++++++++++++++++++++++++
21
3 files changed, 35 insertions(+)
22
23
diff --git a/include/block/block.h b/include/block/block.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block.h
26
+++ b/include/block/block.h
27
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
28
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
29
const char *backing,
30
Error **errp);
31
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
32
33
int path_has_protocol(const char *path);
34
int path_is_absolute(const char *path);
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int.h
38
+++ b/include/block/block_int.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
41
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
42
43
+ /*
44
+ * Returns an allocated string which is the directory name of this BDS: It
45
+ * will be used to make relative filenames absolute by prepending this
46
+ * function's return value to them.
47
+ */
48
+ char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
49
+
50
/* aio */
51
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
52
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
53
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
56
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
58
}
59
}
60
61
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
62
+{
63
+ BlockDriver *drv = bs->drv;
64
+
65
+ if (!drv) {
66
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
67
+ return NULL;
68
+ }
69
+
70
+ if (drv->bdrv_dirname) {
71
+ return drv->bdrv_dirname(bs, errp);
72
+ }
73
+
74
+ if (bs->file) {
75
+ return bdrv_dirname(bs->file->bs, errp);
76
+ }
77
+
78
+ bdrv_refresh_filename(bs);
79
+ if (bs->exact_filename[0] != '\0') {
80
+ return path_combine(bs->exact_filename, "");
81
+ }
82
+
83
+ error_setg(errp, "Cannot generate a base directory for %s nodes",
84
+ drv->format_name);
85
+ return NULL;
86
+}
87
+
88
/*
89
* Hot add/remove a BDS's child. So the user can take a child offline when
90
* it is broken and take a new child online
91
--
92
2.20.1
93
94
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
blkverify's BDSs have a file BDS, but we do not want this to be
4
preferred over the raw node. There is no way to decide between the two
5
(and not really a reason to, either), so just return NULL in blkverify's
6
implementation of bdrv_dirname().
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-16-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/blkverify.c | 10 ++++++++++
15
1 file changed, 10 insertions(+)
16
17
diff --git a/block/blkverify.c b/block/blkverify.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
20
+++ b/block/blkverify.c
21
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
22
}
23
}
24
25
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
26
+{
27
+ /* In general, there are two BDSs with different dirnames below this one;
28
+ * so there is no unique dirname we could return (unless both are equal by
29
+ * chance). Therefore, to be consistent, just always return NULL. */
30
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
31
+ return NULL;
32
+}
33
+
34
static BlockDriver bdrv_blkverify = {
35
.format_name = "blkverify",
36
.protocol_name = "blkverify",
37
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
38
.bdrv_child_perm = bdrv_filter_default_perms,
39
.bdrv_getlength = blkverify_getlength,
40
.bdrv_refresh_filename = blkverify_refresh_filename,
41
+ .bdrv_dirname = blkverify_dirname,
42
43
.bdrv_co_preadv = blkverify_co_preadv,
44
.bdrv_co_pwritev = blkverify_co_pwritev,
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
While the common implementation for bdrv_dirname() should return NULL
4
for quorum BDSs already (because they do not have a file node and their
5
exact_filename field should be empty), there is no reason not to make
6
that explicit.
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-17-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/quorum.c | 11 +++++++++++
15
1 file changed, 11 insertions(+)
16
17
diff --git a/block/quorum.c b/block/quorum.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
20
+++ b/block/quorum.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
22
bs->full_open_options = opts;
23
}
24
25
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
26
+{
27
+ /* In general, there are multiple BDSs with different dirnames below this
28
+ * one; so there is no unique dirname we could return (unless all are equal
29
+ * by chance, or there is only one). Therefore, to be consistent, just
30
+ * always return NULL. */
31
+ error_setg(errp, "Cannot generate a base directory for quorum nodes");
32
+ return NULL;
33
+}
34
+
35
static BlockDriver bdrv_quorum = {
36
.format_name = "quorum",
37
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
39
.bdrv_open = quorum_open,
40
.bdrv_close = quorum_close,
41
.bdrv_refresh_filename = quorum_refresh_filename,
42
+ .bdrv_dirname = quorum_dirname,
43
44
.bdrv_co_flush_to_disk = quorum_co_flush,
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
The generic bdrv_dirname() implementation would be able to generate some
4
form of directory name for many NBD nodes, but it would be always wrong.
5
Therefore, we have to explicitly make it an error (until NBD has some
6
form of specification for export paths, if it ever will).
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20190201192935.18394-18-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/nbd.c | 13 +++++++++++++
15
1 file changed, 13 insertions(+)
16
17
diff --git a/block/nbd.c b/block/nbd.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/nbd.c
20
+++ b/block/nbd.c
21
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
22
bs->full_open_options = opts;
23
}
24
25
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
26
+{
27
+ /* The generic bdrv_dirname() implementation is able to work out some
28
+ * directory name for NBD nodes, but that would be wrong. So far there is no
29
+ * specification for how "export paths" would work, so NBD does not have
30
+ * directory names. */
31
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
32
+ return NULL;
33
+}
34
+
35
static BlockDriver bdrv_nbd = {
36
.format_name = "nbd",
37
.protocol_name = "nbd",
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
39
.bdrv_attach_aio_context = nbd_attach_aio_context,
40
.bdrv_refresh_filename = nbd_refresh_filename,
41
.bdrv_co_block_status = nbd_client_co_block_status,
42
+ .bdrv_dirname = nbd_dirname,
43
};
44
45
static BlockDriver bdrv_nbd_tcp = {
46
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
47
.bdrv_attach_aio_context = nbd_attach_aio_context,
48
.bdrv_refresh_filename = nbd_refresh_filename,
49
.bdrv_co_block_status = nbd_client_co_block_status,
50
+ .bdrv_dirname = nbd_dirname,
51
};
52
53
static BlockDriver bdrv_nbd_unix = {
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
55
.bdrv_attach_aio_context = nbd_attach_aio_context,
56
.bdrv_refresh_filename = nbd_refresh_filename,
57
.bdrv_co_block_status = nbd_client_co_block_status,
58
+ .bdrv_dirname = nbd_dirname,
59
};
60
61
static void bdrv_nbd_init(void)
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
While the basic idea is obvious and could be handled by the default
4
bdrv_dirname() implementation, we cannot generate a directory name if
5
the gid or uid are set, so we have to explicitly return NULL in those
6
cases.
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-19-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/nfs.c | 15 +++++++++++++++
14
1 file changed, 15 insertions(+)
15
16
diff --git a/block/nfs.c b/block/nfs.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nfs.c
19
+++ b/block/nfs.c
20
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
21
bs->full_open_options = opts;
22
}
23
24
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
25
+{
26
+ NFSClient *client = bs->opaque;
27
+
28
+ if (client->uid || client->gid) {
29
+ bdrv_refresh_filename(bs);
30
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
31
+ bs->filename);
32
+ return NULL;
33
+ }
34
+
35
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
36
+}
37
+
38
#ifdef LIBNFS_FEATURE_PAGECACHE
39
static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
40
Error **errp)
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
42
.bdrv_detach_aio_context = nfs_detach_aio_context,
43
.bdrv_attach_aio_context = nfs_attach_aio_context,
44
.bdrv_refresh_filename = nfs_refresh_filename,
45
+ .bdrv_dirname = nfs_dirname,
46
47
#ifdef LIBNFS_FEATURE_PAGECACHE
48
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
bdrv_get_full_backing_filename_from_filename() breaks down when it comes
4
to JSON filenames. Using bdrv_dirname() as the basis is better because
5
since we have BDS, we can descend through the BDS tree to the protocol
6
layer, which gives us a greater probability of finding a non-JSON name;
7
also, bdrv_dirname() is more correct as it allows block drivers to
8
override the generation of that directory name in a protocol-specific
9
way.
10
11
We still need to keep bdrv_get_full_backing_filename_from_filename(),
12
though, because it has valid callers which need it during image creation
13
when no BDS is available yet.
14
15
This makes a test case in qemu-iotest 110, which was supposed to fail,
16
work. That is actually good, but we need to change the reference output
17
(and the comment in 110) accordingly.
18
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Reviewed-by: Alberto Garcia <berto@igalia.com>
21
Message-id: 20190201192935.18394-20-mreitz@redhat.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
block.c | 20 +++++++++++++-------
25
tests/qemu-iotests/110 | 3 ++-
26
tests/qemu-iotests/110.out | 2 +-
27
3 files changed, 16 insertions(+), 9 deletions(-)
28
29
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
32
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
34
static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
35
const char *filename, Error **errp)
36
{
37
- char *bs_filename;
38
+ char *dir, *full_name;
39
40
- bdrv_refresh_filename(relative_to);
41
+ if (!filename || filename[0] == '\0') {
42
+ return NULL;
43
+ } else if (path_has_protocol(filename) || path_is_absolute(filename)) {
44
+ return g_strdup(filename);
45
+ }
46
47
- bs_filename = relative_to->exact_filename[0]
48
- ? relative_to->exact_filename
49
- : relative_to->filename;
50
+ dir = bdrv_dirname(relative_to, errp);
51
+ if (!dir) {
52
+ return NULL;
53
+ }
54
55
- return bdrv_get_full_backing_filename_from_filename(bs_filename,
56
- filename ?: "", errp);
57
+ full_name = g_strconcat(dir, filename, NULL);
58
+ g_free(dir);
59
+ return full_name;
60
}
61
62
char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
63
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
64
index XXXXXXX..XXXXXXX 100755
65
--- a/tests/qemu-iotests/110
66
+++ b/tests/qemu-iotests/110
67
@@ -XXX,XX +XXX,XX @@ echo '=== Non-reconstructable filename ==='
68
echo
69
70
# Across blkdebug without a config file, you cannot reconstruct filenames, so
71
-# qemu is incapable of knowing the directory of the top image
72
+# qemu is incapable of knowing the directory of the top image from the filename
73
+# alone. However, using bdrv_dirname(), it should still work.
74
TEST_IMG="json:{
75
'driver': '$IMGFMT',
76
'file': {
77
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/110.out
80
+++ b/tests/qemu-iotests/110.out
81
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
82
image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
83
file format: IMGFMT
84
virtual size: 64M (67108864 bytes)
85
-backing file: t.IMGFMT.base (cannot determine actual path)
86
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
87
88
=== Backing name is always relative to the backed image ===
89
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Test 110 tests relative backing filenames for complex BDS trees. Now
4
that the originally supposedly failing test passes, let us add a new
5
failing test: Quorum can never work automatically (without detecting
6
whether all child nodes have the same base directory, but that would be
7
rather inconsistent behavior).
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-21-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/110 | 26 ++++++++++++++++++++++++++
15
tests/qemu-iotests/110.out | 7 +++++++
16
2 files changed, 33 insertions(+)
17
18
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/110
21
+++ b/tests/qemu-iotests/110
22
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
23
_cleanup()
24
{
25
    _cleanup_test_img
26
+ rm -f "$TEST_IMG.copy"
27
}
28
trap "_cleanup; exit \$status" 0 1 2 3 15
29
30
@@ -XXX,XX +XXX,XX @@ echo
31
# omit the image size; it should work anyway
32
_make_test_img -b "$TEST_IMG_REL.base"
33
34
+echo
35
+echo '=== Nodes without a common directory ==='
36
+echo
37
+
38
+cp "$TEST_IMG" "$TEST_IMG.copy"
39
+
40
+# Should inform us that the actual path of the backing file cannot be determined
41
+TEST_IMG="json:{
42
+ 'driver': '$IMGFMT',
43
+ 'file': {
44
+ 'driver': 'quorum',
45
+ 'vote-threshold': 1,
46
+ 'children': [
47
+ {
48
+ 'driver': 'file',
49
+ 'filename': '$TEST_IMG'
50
+ },
51
+ {
52
+ 'driver': 'file',
53
+ 'filename': '$TEST_IMG.copy'
54
+ }
55
+ ]
56
+ }
57
+}" _img_info | _filter_img_info
58
+
59
60
# success, all done
61
echo '*** done'
62
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/110.out
65
+++ b/tests/qemu-iotests/110.out
66
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
67
=== Backing name is always relative to the backed image ===
68
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
70
+
71
+=== Nodes without a common directory ===
72
+
73
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "blkverify": false, "rewrite-corrupted": false, "vote-threshold": 1}}
74
+file format: IMGFMT
75
+virtual size: 64M (67108864 bytes)
76
+backing file: t.IMGFMT.base (cannot determine actual path)
77
*** done
78
--
79
2.20.1
80
81
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Some follow-up patches will rework the way bs->full_open_options is
4
refreshed in bdrv_refresh_filename(). The new implementation will remove
5
the need for the block drivers' bdrv_refresh_filename() implementations
6
to set bs->full_open_options; instead, it will be generic and use static
7
information from each block driver.
8
9
However, by implementing bdrv_gather_child_options(), block drivers will
10
still be able to override the way the full_open_options of their
11
children are incorporated into their own.
12
13
We need to implement this function for VMDK because we have to prevent
14
the generic implementation from gathering the options of all children:
15
It is not possible to specify options for the extents through the
16
runtime options.
17
18
For quorum, the child names that would be used by the generic
19
implementation and the ones that we actually (currently) want to use
20
differ. See quorum_gather_child_options() for more information.
21
22
Note that both of these are cases which are not ideal: In case of VMDK
23
it would probably be nice to be able to specify options for all extents.
24
In case of quorum, the current runtime option structure is simply broken
25
and needs to be fixed (but that is left for another patch).
26
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
Reviewed-by: Alberto Garcia <berto@igalia.com>
29
Message-id: 20190201192935.18394-23-mreitz@redhat.com
30
Signed-off-by: Max Reitz <mreitz@redhat.com>
31
---
32
include/block/block_int.h | 24 +++++++++++++++++++++++
33
block/quorum.c | 40 +++++++++++++++++++++++++++++++++++++++
34
block/vmdk.c | 19 +++++++++++++++++++
35
3 files changed, 83 insertions(+)
36
37
diff --git a/include/block/block_int.h b/include/block/block_int.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block_int.h
40
+++ b/include/block/block_int.h
41
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
42
43
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
44
45
+ /*
46
+ * Gathers the open options for all children into @target.
47
+ * A simple format driver (without backing file support) might
48
+ * implement this function like this:
49
+ *
50
+ * QINCREF(bs->file->bs->full_open_options);
51
+ * qdict_put(target, "file", bs->file->bs->full_open_options);
52
+ *
53
+ * If not specified, the generic implementation will simply put
54
+ * all children's options under their respective name.
55
+ *
56
+ * @backing_overridden is true when bs->backing seems not to be
57
+ * the child that would result from opening bs->backing_file.
58
+ * Therefore, if it is true, the backing child's options should be
59
+ * gathered; otherwise, there is no need since the backing child
60
+ * is the one implied by the image header.
61
+ *
62
+ * Note that ideally this function would not be needed. Every
63
+ * block driver which implements it is probably doing something
64
+ * shady regarding its runtime option structure.
65
+ */
66
+ void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
67
+ bool backing_overridden);
68
+
69
/*
70
* Returns an allocated string which is the directory name of this BDS: It
71
* will be used to make relative filenames absolute by prepending this
72
diff --git a/block/quorum.c b/block/quorum.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/quorum.c
75
+++ b/block/quorum.c
76
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
77
bs->full_open_options = opts;
78
}
79
80
+static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
81
+ bool backing_overridden)
82
+{
83
+ BDRVQuorumState *s = bs->opaque;
84
+ QList *children_list;
85
+ int i;
86
+
87
+ /*
88
+ * The generic implementation for gathering child options in
89
+ * bdrv_refresh_filename() would use the names of the children
90
+ * as specified for bdrv_open_child() or bdrv_attach_child(),
91
+ * which is "children.%u" with %u being a value
92
+ * (s->next_child_index) that is incremented each time a new child
93
+ * is added (and never decremented). Since children can be
94
+ * deleted at runtime, there may be gaps in that enumeration.
95
+ * When creating a new quorum BDS and specifying the children for
96
+ * it through runtime options, the enumeration used there may not
97
+ * have any gaps, though.
98
+ *
99
+ * Therefore, we have to create a new gap-less enumeration here
100
+ * (which we can achieve by simply putting all of the children's
101
+ * full_open_options into a QList).
102
+ *
103
+ * XXX: Note that there are issues with the current child option
104
+ * structure quorum uses (such as the fact that children do
105
+ * not really have unique permanent names). Therefore, this
106
+ * is going to have to change in the future and ideally we
107
+ * want quorum to be covered by the generic implementation.
108
+ */
109
+
110
+ children_list = qlist_new();
111
+ qdict_put(target, "children", children_list);
112
+
113
+ for (i = 0; i < s->num_children; i++) {
114
+ qlist_append(children_list,
115
+ qobject_ref(s->children[i]->bs->full_open_options));
116
+ }
117
+}
118
+
119
static char *quorum_dirname(BlockDriverState *bs, Error **errp)
120
{
121
/* In general, there are multiple BDSs with different dirnames below this
122
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
123
.bdrv_open = quorum_open,
124
.bdrv_close = quorum_close,
125
.bdrv_refresh_filename = quorum_refresh_filename,
126
+ .bdrv_gather_child_options = quorum_gather_child_options,
127
.bdrv_dirname = quorum_dirname,
128
129
.bdrv_co_flush_to_disk = quorum_co_flush,
130
diff --git a/block/vmdk.c b/block/vmdk.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/vmdk.c
133
+++ b/block/vmdk.c
134
@@ -XXX,XX +XXX,XX @@
135
#include "qapi/error.h"
136
#include "block/block_int.h"
137
#include "sysemu/block-backend.h"
138
+#include "qapi/qmp/qdict.h"
139
#include "qapi/qmp/qerror.h"
140
#include "qemu/error-report.h"
141
#include "qemu/module.h"
142
@@ -XXX,XX +XXX,XX @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
143
return 0;
144
}
145
146
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
147
+ bool backing_overridden)
148
+{
149
+ /* No children but file and backing can be explicitly specified (TODO) */
150
+ qdict_put(target, "file",
151
+ qobject_ref(bs->file->bs->full_open_options));
152
+
153
+ if (backing_overridden) {
154
+ if (bs->backing) {
155
+ qdict_put(target, "backing",
156
+ qobject_ref(bs->backing->bs->full_open_options));
157
+ } else {
158
+ qdict_put_null(target, "backing");
159
+ }
160
+ }
161
+}
162
+
163
static QemuOptsList vmdk_create_opts = {
164
.name = "vmdk-create-opts",
165
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
166
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
167
.bdrv_get_specific_info = vmdk_get_specific_info,
168
.bdrv_refresh_limits = vmdk_refresh_limits,
169
.bdrv_get_info = vmdk_get_info,
170
+ .bdrv_gather_child_options = vmdk_gather_child_options,
171
172
.supports_backing = true,
173
.create_opts = &vmdk_create_opts,
174
--
175
2.20.1
176
177
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Instead of having every block driver which implements
4
bdrv_refresh_filename() copy all of the strong runtime options over to
5
bs->full_open_options, implement this process generically in
6
bdrv_refresh_filename().
7
8
This patch only adds this new generic implementation, it does not remove
9
the old functionality. This is done in a follow-up patch.
10
11
With this patch, some superfluous information (that should never have
12
been there) may be removed from some JSON filenames, as can be seen in
13
the change to iotests 110's and 228's reference outputs.
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-id: 20190201192935.18394-24-mreitz@redhat.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block.c | 116 ++++++++++++++++++++++++++++++++++++-
20
tests/qemu-iotests/110.out | 2 +-
21
tests/qemu-iotests/228 | 7 ++-
22
tests/qemu-iotests/228.out | 2 +-
23
4 files changed, 121 insertions(+), 6 deletions(-)
24
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ out:
30
return to_replace_bs;
31
}
32
33
+/**
34
+ * Iterates through the list of runtime option keys that are said to
35
+ * be "strong" for a BDS. An option is called "strong" if it changes
36
+ * a BDS's data. For example, the null block driver's "size" and
37
+ * "read-zeroes" options are strong, but its "latency-ns" option is
38
+ * not.
39
+ *
40
+ * If a key returned by this function ends with a dot, all options
41
+ * starting with that prefix are strong.
42
+ */
43
+static const char *const *strong_options(BlockDriverState *bs,
44
+ const char *const *curopt)
45
+{
46
+ static const char *const global_options[] = {
47
+ "driver", "filename", NULL
48
+ };
49
+
50
+ if (!curopt) {
51
+ return &global_options[0];
52
+ }
53
+
54
+ curopt++;
55
+ if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) {
56
+ curopt = bs->drv->strong_runtime_opts;
57
+ }
58
+
59
+ return (curopt && *curopt) ? curopt : NULL;
60
+}
61
+
62
+/**
63
+ * Copies all strong runtime options from bs->options to the given
64
+ * QDict. The set of strong option keys is determined by invoking
65
+ * strong_options().
66
+ *
67
+ * Returns true iff any strong option was present in bs->options (and
68
+ * thus copied to the target QDict) with the exception of "filename"
69
+ * and "driver". The caller is expected to use this value to decide
70
+ * whether the existence of strong options prevents the generation of
71
+ * a plain filename.
72
+ */
73
+static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
74
+{
75
+ bool found_any = false;
76
+ const char *const *option_name = NULL;
77
+
78
+ if (!bs->drv) {
79
+ return false;
80
+ }
81
+
82
+ while ((option_name = strong_options(bs, option_name))) {
83
+ bool option_given = false;
84
+
85
+ assert(strlen(*option_name) > 0);
86
+ if ((*option_name)[strlen(*option_name) - 1] != '.') {
87
+ QObject *entry = qdict_get(bs->options, *option_name);
88
+ if (!entry) {
89
+ continue;
90
+ }
91
+
92
+ qdict_put_obj(d, *option_name, qobject_ref(entry));
93
+ option_given = true;
94
+ } else {
95
+ const QDictEntry *entry;
96
+ for (entry = qdict_first(bs->options); entry;
97
+ entry = qdict_next(bs->options, entry))
98
+ {
99
+ if (strstart(qdict_entry_key(entry), *option_name, NULL)) {
100
+ qdict_put_obj(d, qdict_entry_key(entry),
101
+ qobject_ref(qdict_entry_value(entry)));
102
+ option_given = true;
103
+ }
104
+ }
105
+ }
106
+
107
+ /* While "driver" and "filename" need to be included in a JSON filename,
108
+ * their existence does not prohibit generation of a plain filename. */
109
+ if (!found_any && option_given &&
110
+ strcmp(*option_name, "driver") && strcmp(*option_name, "filename"))
111
+ {
112
+ found_any = true;
113
+ }
114
+ }
115
+
116
+ return found_any;
117
+}
118
+
119
static bool append_open_options(QDict *d, BlockDriverState *bs)
120
{
121
const QDictEntry *entry;
122
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
123
bs->full_open_options = opts;
124
}
125
126
+ /* Gather the options QDict */
127
+ opts = qdict_new();
128
+ append_strong_runtime_options(opts, bs);
129
+
130
+ if (drv->bdrv_gather_child_options) {
131
+ /* Some block drivers may not want to present all of their children's
132
+ * options, or name them differently from BdrvChild.name */
133
+ drv->bdrv_gather_child_options(bs, opts, backing_overridden);
134
+ } else {
135
+ QLIST_FOREACH(child, &bs->children, next) {
136
+ if (child->role == &child_backing && !backing_overridden) {
137
+ /* We can skip the backing BDS if it has not been overridden */
138
+ continue;
139
+ }
140
+
141
+ qdict_put(opts, child->name,
142
+ qobject_ref(child->bs->full_open_options));
143
+ }
144
+
145
+ if (backing_overridden && !bs->backing) {
146
+ /* Force no backing file */
147
+ qdict_put_null(opts, "backing");
148
+ }
149
+ }
150
+
151
+ qobject_unref(bs->full_open_options);
152
+ bs->full_open_options = opts;
153
+
154
if (bs->exact_filename[0]) {
155
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
156
- } else if (bs->full_open_options) {
157
+ } else {
158
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
159
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
160
qstring_get_str(json));
161
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
162
index XXXXXXX..XXXXXXX 100644
163
--- a/tests/qemu-iotests/110.out
164
+++ b/tests/qemu-iotests/110.out
165
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
166
167
=== Nodes without a common directory ===
168
169
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "blkverify": false, "rewrite-corrupted": false, "vote-threshold": 1}}
170
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
171
file format: IMGFMT
172
virtual size: 64M (67108864 bytes)
173
backing file: t.IMGFMT.base (cannot determine actual path)
174
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
175
index XXXXXXX..XXXXXXX 100755
176
--- a/tests/qemu-iotests/228
177
+++ b/tests/qemu-iotests/228
178
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
179
overlay='node0')
180
181
# This should give us the original plain result
182
- # FIXME: Currently, the block layer considers the runtime backing
183
- # file to be different from the image header, which is
184
- # wrong. This is fixed by a future patch.
185
+ # FIXME: Currently, it yields a json:{} filename even though it
186
+ # only contains a @driver and a @file entry, so a plain
187
+ # filename would obviously suffice. This is fixed by a
188
+ # future patch.
189
190
log_node_info(vm.node_info('node0'))
191
192
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
193
index XXXXXXX..XXXXXXX 100644
194
--- a/tests/qemu-iotests/228.out
195
+++ b/tests/qemu-iotests/228.out
196
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
197
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
198
{"return": {}}
199
200
-bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
201
+bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
202
bs->backing_file: TEST_DIR/PID-base.img
203
bs->backing->bs->filename: TEST_DIR/PID-base.img
204
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
If a format BDS's file BDS is in turn a format BDS, we cannot simply use
4
the same filename, because when opening a BDS tree based on a filename
5
alone, qemu will create only one format node on top of one protocol node
6
(disregarding a potential backing file).
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-26-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block.c | 18 +++++++++++++++---
14
1 file changed, 15 insertions(+), 3 deletions(-)
15
16
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
21
22
bs->exact_filename[0] = '\0';
23
24
- /* If no specific options have been given for this BDS, the filename of
25
- * the underlying file should suffice for this one as well */
26
- if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
27
+ /*
28
+ * We can use the underlying file's filename if:
29
+ * - it has a filename,
30
+ * - the file is a protocol BDS, and
31
+ * - opening that file (as this BDS's format) will automatically create
32
+ * the BDS tree we have right now, that is:
33
+ * - the user did not significantly change this BDS's behavior with
34
+ * some explicit (strong) options
35
+ * - no non-file child of this BDS has been overridden by the user
36
+ * Both of these conditions are represented by generate_json_filename.
37
+ */
38
+ if (bs->file->bs->exact_filename[0] &&
39
+ bs->file->bs->drv->bdrv_file_open &&
40
+ !generate_json_filename)
41
+ {
42
strcpy(bs->exact_filename, bs->file->bs->exact_filename);
43
}
44
}
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Currently, nvme's bdrv_refresh_filename() is an exact copy of null's
4
implementation. However, for null, "null-co://" and "null-aio://" are
5
indeed valid filenames -- for nvme, they are not, as a device address is
6
still required.
7
8
The correct implementation should generate a filename of the form
9
"nvme://[PCI address]/[namespace]" (as the comment above
10
nvme_parse_filename() describes).
11
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Alberto Garcia <berto@igalia.com>
14
Message-id: 20190201192935.18394-27-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/nvme.c | 23 +++++++++--------------
18
1 file changed, 9 insertions(+), 14 deletions(-)
19
20
diff --git a/block/nvme.c b/block/nvme.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/nvme.c
23
+++ b/block/nvme.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
25
26
/* Total size of mapped qiov, accessed under dma_map_lock */
27
int dma_map_count;
28
+
29
+ /* PCI address (required for nvme_refresh_filename()) */
30
+ char *device;
31
} BDRVNVMeState;
32
33
#define NVME_BLOCK_OPT_DEVICE "device"
34
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
35
36
qemu_co_mutex_init(&s->dma_map_lock);
37
qemu_co_queue_init(&s->dma_flush_queue);
38
+ s->device = g_strdup(device);
39
s->nsid = namespace;
40
s->aio_context = bdrv_get_aio_context(bs);
41
ret = event_notifier_init(&s->irq_notifier, 0);
42
@@ -XXX,XX +XXX,XX @@ static void nvme_close(BlockDriverState *bs)
43
event_notifier_cleanup(&s->irq_notifier);
44
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
45
qemu_vfio_close(s->vfio);
46
+
47
+ g_free(s->device);
48
}
49
50
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
51
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
52
53
static void nvme_refresh_filename(BlockDriverState *bs)
54
{
55
- const QDictEntry *e;
56
-
57
- for (e = qdict_first(bs->full_open_options); e;
58
- e = qdict_next(bs->full_open_options, e))
59
- {
60
- /* These options can be ignored */
61
- if (strcmp(qdict_entry_key(e), "filename") &&
62
- strcmp(qdict_entry_key(e), "driver"))
63
- {
64
- return;
65
- }
66
- }
67
+ BDRVNVMeState *s = bs->opaque;
68
69
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
70
- bs->drv->format_name);
71
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nvme://%s/%i",
72
+ s->device, s->nsid);
73
}
74
75
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Both of the defaults we currently have in the curl driver are named
4
based on a slightly different schema, let's unify that and call both
5
CURL_BLOCK_OPT_${NAME}_DEFAULT.
6
7
While at it, we can add a macro for the third option for which a default
8
exists, namely "sslverify".
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20190201192935.18394-28-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/curl.c | 13 ++++++++-----
16
1 file changed, 8 insertions(+), 5 deletions(-)
17
18
diff --git a/block/curl.c b/block/curl.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/curl.c
21
+++ b/block/curl.c
22
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
23
24
#define CURL_NUM_STATES 8
25
#define CURL_NUM_ACB 8
26
-#define READ_AHEAD_DEFAULT (256 * 1024)
27
-#define CURL_TIMEOUT_DEFAULT 5
28
#define CURL_TIMEOUT_MAX 10000
29
30
#define CURL_BLOCK_OPT_URL "url"
31
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
32
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
33
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
34
35
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
36
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
37
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
38
+
39
struct BDRVCURLState;
40
41
static bool libcurl_initialized;
42
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
43
}
44
45
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
46
- READ_AHEAD_DEFAULT);
47
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
48
if ((s->readahead_size & 0x1ff) != 0) {
49
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
50
s->readahead_size);
51
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
52
}
53
54
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
55
- CURL_TIMEOUT_DEFAULT);
56
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
57
if (s->timeout > CURL_TIMEOUT_MAX) {
58
error_setg(errp, "timeout parameter is too large or negative");
59
goto out_noclean;
60
}
61
62
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
63
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
64
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
65
66
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
67
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
68
--
69
2.20.1
70
71
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Message-id: 20190201192935.18394-29-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/curl.c | 21 +++++++++++++++++++++
9
1 file changed, 21 insertions(+)
10
11
diff --git a/block/curl.c b/block/curl.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/curl.c
14
+++ b/block/curl.c
15
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
16
return s->len;
17
}
18
19
+static void curl_refresh_filename(BlockDriverState *bs)
20
+{
21
+ BDRVCURLState *s = bs->opaque;
22
+
23
+ /* "readahead" and "timeout" do not change the guest-visible data,
24
+ * so ignore them */
25
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
26
+ s->cookie || s->username || s->password || s->proxyusername ||
27
+ s->proxypassword)
28
+ {
29
+ return;
30
+ }
31
+
32
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
33
+}
34
+
35
+
36
static const char *const curl_strong_runtime_opts[] = {
37
CURL_BLOCK_OPT_URL,
38
CURL_BLOCK_OPT_SSLVERIFY,
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
40
.bdrv_detach_aio_context = curl_detach_aio_context,
41
.bdrv_attach_aio_context = curl_attach_aio_context,
42
43
+ .bdrv_refresh_filename = curl_refresh_filename,
44
.strong_runtime_opts = curl_strong_runtime_opts,
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
48
.bdrv_detach_aio_context = curl_detach_aio_context,
49
.bdrv_attach_aio_context = curl_attach_aio_context,
50
51
+ .bdrv_refresh_filename = curl_refresh_filename,
52
.strong_runtime_opts = curl_strong_runtime_opts,
53
};
54
55
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
56
.bdrv_detach_aio_context = curl_detach_aio_context,
57
.bdrv_attach_aio_context = curl_attach_aio_context,
58
59
+ .bdrv_refresh_filename = curl_refresh_filename,
60
.strong_runtime_opts = curl_strong_runtime_opts,
61
};
62
63
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
64
.bdrv_detach_aio_context = curl_detach_aio_context,
65
.bdrv_attach_aio_context = curl_attach_aio_context,
66
67
+ .bdrv_refresh_filename = curl_refresh_filename,
68
.strong_runtime_opts = curl_strong_runtime_opts,
69
};
70
71
--
72
2.20.1
73
74
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
While we cannot represent the latency-ns option in a filename, it is not
4
a strong option so not being able to should not stop us from generating
5
a filename nonetheless.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-id: 20190201192935.18394-30-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/null.c | 3 ++-
13
1 file changed, 2 insertions(+), 1 deletion(-)
14
15
diff --git a/block/null.c b/block/null.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/null.c
18
+++ b/block/null.c
19
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs)
20
{
21
/* These options can be ignored */
22
if (strcmp(qdict_entry_key(e), "filename") &&
23
- strcmp(qdict_entry_key(e), "driver"))
24
+ strcmp(qdict_entry_key(e), "driver") &&
25
+ strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
26
{
27
return;
28
}
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
When BDSs are created by qemu itself (e.g. as filters in block jobs),
4
they may not have a "driver" option in their options QDict. When
5
generating a json:{} filename, however, it must always be present.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-id: 20190201192935.18394-31-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block.c | 6 ++++++
13
1 file changed, 6 insertions(+)
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 bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
20
}
21
}
22
23
+ if (!qdict_haskey(d, "driver")) {
24
+ /* Drivers created with bdrv_new_open_driver() may not have a
25
+ * @driver option. Add it here. */
26
+ qdict_put_str(d, "driver", bs->drv->format_name);
27
+ }
28
+
29
return found_any;
30
}
31
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
A previous commit removed the default filters for qmp_log with the
4
intention to make them explicit; but this happened only for test 206.
5
There are more tests (for more exotic image formats than qcow2) which
6
require the filename filter, though.
7
8
Note that 237 is still broken for Python 2.x, which is fixed in the next
9
commit.
10
11
Fixes: f8ca8609d8549def45b28e82ecac64adaeee9f12
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Message-id: 20190210145736.1486-2-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/210 | 5 +++--
18
tests/qemu-iotests/211 | 5 +++--
19
tests/qemu-iotests/212 | 5 +++--
20
tests/qemu-iotests/213 | 5 +++--
21
tests/qemu-iotests/237 | 5 +++--
22
5 files changed, 15 insertions(+), 10 deletions(-)
23
24
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/210
27
+++ b/tests/qemu-iotests/210
28
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['luks'])
29
iotests.verify_protocol(supported=['file'])
30
31
def blockdev_create(vm, options):
32
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
33
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
34
+ filters=[iotests.filter_qmp_testfiles])
35
36
if 'return' in result:
37
assert result['return'] == {}
38
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.luks') as disk_path, \
39
'size': 0 })
40
41
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
42
- node_name='imgfile')
43
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
44
45
blockdev_create(vm, { 'driver': imgfmt,
46
'file': 'imgfile',
47
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
48
index XXXXXXX..XXXXXXX 100755
49
--- a/tests/qemu-iotests/211
50
+++ b/tests/qemu-iotests/211
51
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['vdi'])
52
iotests.verify_protocol(supported=['file'])
53
54
def blockdev_create(vm, options):
55
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
56
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
57
+ filters=[iotests.filter_qmp_testfiles])
58
59
if 'return' in result:
60
assert result['return'] == {}
61
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vdi') as disk_path, \
62
'size': 0 })
63
64
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
65
- node_name='imgfile')
66
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
67
68
blockdev_create(vm, { 'driver': imgfmt,
69
'file': 'imgfile',
70
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
71
index XXXXXXX..XXXXXXX 100755
72
--- a/tests/qemu-iotests/212
73
+++ b/tests/qemu-iotests/212
74
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['parallels'])
75
iotests.verify_protocol(supported=['file'])
76
77
def blockdev_create(vm, options):
78
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
79
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
80
+ filters=[iotests.filter_qmp_testfiles])
81
82
if 'return' in result:
83
assert result['return'] == {}
84
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.parallels') as disk_path, \
85
'size': 0 })
86
87
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
88
- node_name='imgfile')
89
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
90
91
blockdev_create(vm, { 'driver': imgfmt,
92
'file': 'imgfile',
93
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
94
index XXXXXXX..XXXXXXX 100755
95
--- a/tests/qemu-iotests/213
96
+++ b/tests/qemu-iotests/213
97
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['vhdx'])
98
iotests.verify_protocol(supported=['file'])
99
100
def blockdev_create(vm, options):
101
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
102
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
103
+ filters=[iotests.filter_qmp_testfiles])
104
105
if 'return' in result:
106
assert result['return'] == {}
107
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vhdx') as disk_path, \
108
'size': 0 })
109
110
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
111
- node_name='imgfile')
112
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
113
114
blockdev_create(vm, { 'driver': imgfmt,
115
'file': 'imgfile',
116
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
117
index XXXXXXX..XXXXXXX 100755
118
--- a/tests/qemu-iotests/237
119
+++ b/tests/qemu-iotests/237
120
@@ -XXX,XX +XXX,XX @@ from iotests import imgfmt
121
iotests.verify_image_format(supported_fmts=['vmdk'])
122
123
def blockdev_create(vm, options):
124
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
125
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
126
+ filters=[iotests.filter_qmp_testfiles])
127
128
if 'return' in result:
129
assert result['return'] == {}
130
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
131
'size': 0 })
132
133
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
134
- node_name='imgfile')
135
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
136
137
blockdev_create(vm, { 'driver': imgfmt,
138
'file': 'imgfile',
139
--
140
2.20.1
141
142
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
math.ceil() returns an integer on Python 3.x, but a float on Python 2.x.
4
range() always needs integers, so we need an explicit conversion on 2.x
5
(which does not hurt on 3.x).
6
7
It is not quite clear whether we want to support Python 2.x for any
8
prolonged time, but this may as well be fixed along with the other
9
issues some iotests have right now.
10
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20190210145736.1486-3-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/237 | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/237
23
+++ b/tests/qemu-iotests/237
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
25
iotests.log("= %s %d =" % (subfmt, size))
26
iotests.log("")
27
28
- num_extents = math.ceil(size / 2.0**31)
29
+ num_extents = int(math.ceil(size / 2.0**31))
30
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
31
32
vm.launch()
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This test creates no such file.
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-4-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/232 | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/232
17
+++ b/tests/qemu-iotests/232
18
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
19
_cleanup()
20
{
21
_cleanup_test_img
22
- rm -f $TEST_IMG.snap
23
}
24
trap "_cleanup; exit \$status" 0 1 2 3 15
25
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
With IMGOPTSSYNTAX, $TEST_IMG is useless for this test (it only tests
4
the file-posix protocol driver). Therefore, if $TEST_IMG_FILE is set,
5
use that instead.
6
7
Because this test requires the file protocol, $TEST_IMG_FILE will always
8
be set if $IMGOPTSSYNTAX is true.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Message-id: 20190210145736.1486-5-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/232 | 4 ++++
16
1 file changed, 4 insertions(+)
17
18
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/232
21
+++ b/tests/qemu-iotests/232
22
@@ -XXX,XX +XXX,XX @@ size=128M
23
24
_make_test_img $size
25
26
+if [ -n "$TEST_IMG_FILE" ]; then
27
+ TEST_IMG=$TEST_IMG_FILE
28
+fi
29
+
30
echo
31
echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
32
echo
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Fixes: 08fcd6111e1949f456e1b232ebeeb0cc17019a92
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Message-id: 20190210145736.1486-6-mreitz@redhat.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
tests/qemu-iotests/207 | 10 +++++++---
10
tests/qemu-iotests/207.out | 4 ++--
11
2 files changed, 9 insertions(+), 5 deletions(-)
12
13
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/207
16
+++ b/tests/qemu-iotests/207
17
@@ -XXX,XX +XXX,XX @@ import re
18
iotests.verify_image_format(supported_fmts=['raw'])
19
iotests.verify_protocol(supported=['ssh'])
20
21
-def filter_hash(msg):
22
- return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg)
23
+def filter_hash(qmsg):
24
+ def _filter(key, value):
25
+ if key == 'hash' and re.match('[0-9a-f]+', value):
26
+ return 'HASH'
27
+ return value
28
+ return iotests.filter_qmp(qmsg, _filter)
29
30
def blockdev_create(vm, options):
31
result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
32
- filters=[iotests.filter_testfiles, filter_hash])
33
+ filters=[iotests.filter_qmp_testfiles, filter_hash])
34
35
if 'return' in result:
36
assert result['return'] == {}
37
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tests/qemu-iotests/207.out
40
+++ b/tests/qemu-iotests/207.out
41
@@ -XXX,XX +XXX,XX @@ Job failed: remote host key does not match host_key_check 'wrong'
42
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
43
{"return": {}}
44
45
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
46
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
47
{"return": {}}
48
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
49
{"return": {}}
50
@@ -XXX,XX +XXX,XX @@ Job failed: remote host key does not match host_key_check 'wrong'
51
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
52
{"return": {}}
53
54
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
55
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
56
{"return": {}}
57
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
58
{"return": {}}
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
On Python 2.x, strings are not always unicode strings. This function
4
checks whether a given value is a plain string, or a unicode string (if
5
there is a difference).
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: 20190210145736.1486-7-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 6 ++++++
13
1 file changed, 6 insertions(+)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def image_size(img):
20
r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img)
21
return json.loads(r)['virtual-size']
22
23
+def is_str(val):
24
+ if sys.version_info.major >= 3:
25
+ return isinstance(val, str)
26
+ else:
27
+ return isinstance(val, str) or isinstance(val, unicode)
28
+
29
test_dir_re = re.compile(r"%s" % test_dir)
30
def filter_test_dir(msg):
31
return test_dir_re.sub("TEST_DIR", msg)
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
filter_qmp_testfiles() currently filters the filename only for specific
4
keys. However, there are more keys that take filenames (such as
5
block-commit's @top and @base, or ssh's @path), and it does not make
6
sense to list them all here. "$TEST_DIR/$PID-" should have enough
7
entropy not to appear anywhere randomly.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Message-id: 20190210145736.1486-8-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def filter_testfiles(msg):
22
23
def filter_qmp_testfiles(qmsg):
24
def _filter(key, value):
25
- if key == 'filename' or key == 'backing-file':
26
+ if is_str(value):
27
return filter_testfiles(value)
28
return value
29
return filter_qmp(qmsg, _filter)
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
8908b253c4ad5f8874c8d13abec169c696a5cd32 has implemented filtering of
4
remote paths for NFS, but forgot SSH. This patch takes care of that.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-9-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/common.rc | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/common.rc
17
+++ b/tests/qemu-iotests/common.rc
18
@@ -XXX,XX +XXX,XX @@ else
19
TEST_IMG="nbd:127.0.0.1:10810"
20
elif [ "$IMGPROTO" = "ssh" ]; then
21
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
22
+ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
23
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
24
elif [ "$IMGPROTO" = "nfs" ]; then
25
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Adding a telnet monitor for no real purpose on a fixed port is not so
4
great. Just use a null monitor instead.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-10-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/qemu.py | 5 ++---
12
tests/qemu-iotests/045 | 2 +-
13
2 files changed, 3 insertions(+), 4 deletions(-)
14
15
diff --git a/scripts/qemu.py b/scripts/qemu.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/scripts/qemu.py
18
+++ b/scripts/qemu.py
19
@@ -XXX,XX +XXX,XX @@ class QEMUMachine(object):
20
return False
21
22
# This can be used to add an unused monitor instance.
23
- def add_monitor_telnet(self, ip, port):
24
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
25
+ def add_monitor_null(self):
26
self._args.append('-monitor')
27
- self._args.append(args)
28
+ self._args.append('null')
29
30
def add_fd(self, fd, fdset, opaque, opts=''):
31
"""
32
diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
33
index XXXXXXX..XXXXXXX 100755
34
--- a/tests/qemu-iotests/045
35
+++ b/tests/qemu-iotests/045
36
@@ -XXX,XX +XXX,XX @@ class TestSCMFd(iotests.QMPTestCase):
37
qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
38
# Add an unused monitor, to verify it works fine when two monitor
39
# instances present
40
- self.vm.add_monitor_telnet("0",4445)
41
+ self.vm.add_monitor_null()
42
self.vm.launch()
43
44
def tearDown(self):
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This follows what qmp() does, so the output will correspond to the
4
actual QMP command.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190210145736.1486-11-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/206.out | 56 +++++++++++++++++------------------
11
tests/qemu-iotests/207.out | 18 +++++------
12
tests/qemu-iotests/210.out | 28 +++++++++---------
13
tests/qemu-iotests/211.out | 26 ++++++++--------
14
tests/qemu-iotests/212.out | 44 +++++++++++++--------------
15
tests/qemu-iotests/213.out | 46 ++++++++++++++--------------
16
tests/qemu-iotests/237.out | 54 ++++++++++++++++-----------------
17
tests/qemu-iotests/iotests.py | 6 ++--
18
8 files changed, 140 insertions(+), 138 deletions(-)
19
20
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/206.out
23
+++ b/tests/qemu-iotests/206.out
24
@@ -XXX,XX +XXX,XX @@
25
=== Successful image creation (defaults) ===
26
27
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
28
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
29
{"return": {}}
30
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
31
{"return": {}}
32
33
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
34
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
35
{"return": {}}
36
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
37
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
38
{"return": {}}
39
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
40
{"return": {}}
41
@@ -XXX,XX +XXX,XX @@ Format specific information:
42
43
=== Successful image creation (inline blockdev-add, explicit defaults) ===
44
45
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
46
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
47
{"return": {}}
48
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
49
{"return": {}}
50
51
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
52
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
53
{"return": {}}
54
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
55
{"return": {}}
56
@@ -XXX,XX +XXX,XX @@ Format specific information:
57
58
=== Successful image creation (v3 non-default options) ===
59
60
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
61
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
62
{"return": {}}
63
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
64
{"return": {}}
65
66
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
67
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
68
{"return": {}}
69
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
70
{"return": {}}
71
@@ -XXX,XX +XXX,XX @@ Format specific information:
72
73
=== Successful image creation (v2 non-default options) ===
74
75
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
76
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
77
{"return": {}}
78
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
79
{"return": {}}
80
81
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
82
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
83
{"return": {}}
84
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
85
{"return": {}}
86
@@ -XXX,XX +XXX,XX @@ Format specific information:
87
88
=== Successful image creation (encrypted) ===
89
90
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
91
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
92
{"return": {}}
93
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
94
{"return": {}}
95
@@ -XXX,XX +XXX,XX @@ Format specific information:
96
97
=== Invalid BlockdevRef ===
98
99
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
100
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
101
{"return": {}}
102
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
103
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
104
{"return": {}}
105
106
=== Invalid sizes ===
107
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
108
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
109
{"return": {}}
110
Job failed: Image size must be a multiple of 512 bytes
111
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
112
{"return": {}}
113
114
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
115
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
116
{"return": {}}
117
Job failed: Could not resize image: Image size cannot be negative
118
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
119
{"return": {}}
120
121
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
122
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
123
{"return": {}}
124
Job failed: Could not resize image: Image size cannot be negative
125
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
126
{"return": {}}
127
128
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
129
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
130
{"return": {}}
131
Job failed: Could not resize image: Failed to grow the L1 table: File too large
132
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
133
{"return": {}}
134
135
=== Invalid version ===
136
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
137
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
138
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
139
140
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
141
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
142
{"return": {}}
143
Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
144
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
145
{"return": {}}
146
147
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
148
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
149
{"return": {}}
150
Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
151
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
152
{"return": {}}
153
154
=== Invalid backing file options ===
155
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
156
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
157
{"return": {}}
158
Job failed: Backing file and preallocation cannot be used at the same time
159
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
160
{"return": {}}
161
162
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
163
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
164
{"return": {}}
165
Job failed: Backing format cannot be used without backing file
166
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
167
{"return": {}}
168
169
=== Invalid cluster size ===
170
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
171
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
172
{"return": {}}
173
Job failed: Cluster size must be a power of two between 512 and 2048k
174
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
175
{"return": {}}
176
177
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
178
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
179
{"return": {}}
180
Job failed: Cluster size must be a power of two between 512 and 2048k
181
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
182
{"return": {}}
183
184
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
185
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
186
{"return": {}}
187
Job failed: Cluster size must be a power of two between 512 and 2048k
188
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
189
{"return": {}}
190
191
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
192
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
193
{"return": {}}
194
Job failed: Cluster size must be a power of two between 512 and 2048k
195
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
196
{"return": {}}
197
198
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
199
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
200
{"return": {}}
201
Job failed: Could not resize image: Failed to grow the L1 table: File too large
202
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
203
{"return": {}}
204
205
=== Invalid refcount width ===
206
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
207
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
208
{"return": {}}
209
Job failed: Refcount width must be a power of two and may not exceed 64 bits
210
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
211
{"return": {}}
212
213
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
214
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
215
{"return": {}}
216
Job failed: Refcount width must be a power of two and may not exceed 64 bits
217
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
218
{"return": {}}
219
220
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
221
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
222
{"return": {}}
223
Job failed: Refcount width must be a power of two and may not exceed 64 bits
224
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
225
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
226
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/qemu-iotests/207.out
228
+++ b/tests/qemu-iotests/207.out
229
@@ -XXX,XX +XXX,XX @@
230
=== Successful image creation (defaults) ===
231
232
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
233
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
234
{"return": {}}
235
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
236
{"return": {}}
237
@@ -XXX,XX +XXX,XX @@ virtual size: 4.0M (4194304 bytes)
238
239
=== Test host-key-check options ===
240
241
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
242
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
243
{"return": {}}
244
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
245
{"return": {}}
246
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
247
file format: IMGFMT
248
virtual size: 8.0M (8388608 bytes)
249
250
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
251
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
252
{"return": {}}
253
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
254
{"return": {}}
255
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
256
file format: IMGFMT
257
virtual size: 4.0M (4194304 bytes)
258
259
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
260
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
261
{"return": {}}
262
Job failed: remote host key does not match host_key_check 'wrong'
263
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
264
{"return": {}}
265
266
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
267
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
268
{"return": {}}
269
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
270
{"return": {}}
271
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
272
file format: IMGFMT
273
virtual size: 8.0M (8388608 bytes)
274
275
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
276
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
277
{"return": {}}
278
Job failed: remote host key does not match host_key_check 'wrong'
279
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
280
{"return": {}}
281
282
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
283
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
284
{"return": {}}
285
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
286
{"return": {}}
287
@@ -XXX,XX +XXX,XX @@ virtual size: 4.0M (4194304 bytes)
288
289
=== Invalid path and user ===
290
291
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
292
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
293
{"return": {}}
294
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
295
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
296
{"return": {}}
297
298
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
299
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
300
{"return": {}}
301
Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
302
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
303
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
304
index XXXXXXX..XXXXXXX 100644
305
--- a/tests/qemu-iotests/210.out
306
+++ b/tests/qemu-iotests/210.out
307
@@ -XXX,XX +XXX,XX @@
308
=== Successful image creation (defaults) ===
309
310
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
311
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
312
{"return": {}}
313
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
314
{"return": {}}
315
316
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}}
317
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node-name": "imgfile"}}
318
{"return": {}}
319
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
320
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
321
{"return": {}}
322
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
323
{"return": {}}
324
@@ -XXX,XX +XXX,XX @@ Format specific information:
325
326
=== Successful image creation (with non-default options) ===
327
328
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
329
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
330
{"return": {}}
331
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
332
{"return": {}}
333
334
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
335
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
336
{"return": {}}
337
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
338
{"return": {}}
339
@@ -XXX,XX +XXX,XX @@ Format specific information:
340
341
=== Invalid BlockdevRef ===
342
343
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
344
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
345
{"return": {}}
346
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
347
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
348
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
349
350
=== Zero size ===
351
352
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
353
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
354
{"return": {}}
355
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
356
{"return": {}}
357
@@ -XXX,XX +XXX,XX @@ Format specific information:
358
359
=== Invalid sizes ===
360
361
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
362
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
363
{"return": {}}
364
Job failed: The requested file size is too large
365
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
366
{"return": {}}
367
368
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
369
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
370
{"return": {}}
371
Job failed: The requested file size is too large
372
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
373
{"return": {}}
374
375
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
376
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
377
{"return": {}}
378
Job failed: The requested file size is too large
379
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
380
@@ -XXX,XX +XXX,XX @@ Job failed: The requested file size is too large
381
382
=== Resize image with invalid sizes ===
383
384
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}}
385
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}}
386
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
387
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}}
388
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}}
389
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
390
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}}
391
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}}
392
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
393
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}}
394
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": -9223372036854775808}}
395
{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}}
396
image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
397
file format: IMGFMT
398
diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
399
index XXXXXXX..XXXXXXX 100644
400
--- a/tests/qemu-iotests/211.out
401
+++ b/tests/qemu-iotests/211.out
402
@@ -XXX,XX +XXX,XX @@
403
=== Successful image creation (defaults) ===
404
405
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
406
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
407
{"return": {}}
408
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
409
{"return": {}}
410
411
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}}
412
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node-name": "imgfile"}}
413
{"return": {}}
414
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
415
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
416
{"return": {}}
417
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
418
{"return": {}}
419
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
420
421
=== Successful image creation (explicit defaults) ===
422
423
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
424
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
425
{"return": {}}
426
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
427
{"return": {}}
428
429
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
430
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
431
{"return": {}}
432
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
433
{"return": {}}
434
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
435
436
=== Successful image creation (with non-default options) ===
437
438
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
439
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
440
{"return": {}}
441
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
442
{"return": {}}
443
444
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
445
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
446
{"return": {}}
447
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
448
{"return": {}}
449
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
450
451
=== Invalid BlockdevRef ===
452
453
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
454
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
455
{"return": {}}
456
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
457
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
458
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
459
460
=== Zero size ===
461
462
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
463
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
464
{"return": {}}
465
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
466
{"return": {}}
467
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
468
469
=== Maximum size ===
470
471
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
472
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
473
{"return": {}}
474
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
475
{"return": {}}
476
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
477
478
=== Invalid sizes ===
479
480
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
481
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
482
{"return": {}}
483
Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
484
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
485
{"return": {}}
486
487
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
488
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
489
{"return": {}}
490
Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)
491
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
492
{"return": {}}
493
494
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
495
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
496
{"return": {}}
497
Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)
498
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
499
diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
500
index XXXXXXX..XXXXXXX 100644
501
--- a/tests/qemu-iotests/212.out
502
+++ b/tests/qemu-iotests/212.out
503
@@ -XXX,XX +XXX,XX @@
504
=== Successful image creation (defaults) ===
505
506
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
507
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
508
{"return": {}}
509
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
510
{"return": {}}
511
512
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}}
513
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node-name": "imgfile"}}
514
{"return": {}}
515
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
516
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
517
{"return": {}}
518
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
519
{"return": {}}
520
@@ -XXX,XX +XXX,XX @@ virtual size: 128M (134217728 bytes)
521
522
=== Successful image creation (explicit defaults) ===
523
524
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
525
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
526
{"return": {}}
527
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
528
{"return": {}}
529
530
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
531
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
532
{"return": {}}
533
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
534
{"return": {}}
535
@@ -XXX,XX +XXX,XX @@ virtual size: 64M (67108864 bytes)
536
537
=== Successful image creation (with non-default options) ===
538
539
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
540
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
541
{"return": {}}
542
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
543
{"return": {}}
544
545
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
546
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
547
{"return": {}}
548
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
549
{"return": {}}
550
@@ -XXX,XX +XXX,XX @@ virtual size: 32M (33554432 bytes)
551
552
=== Invalid BlockdevRef ===
553
554
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
555
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
556
{"return": {}}
557
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
558
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
559
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
560
561
=== Zero size ===
562
563
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
564
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
565
{"return": {}}
566
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
567
{"return": {}}
568
@@ -XXX,XX +XXX,XX @@ virtual size: 0 (0 bytes)
569
570
=== Maximum size ===
571
572
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
573
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
574
{"return": {}}
575
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
576
{"return": {}}
577
@@ -XXX,XX +XXX,XX @@ virtual size: 4096T (4503599627369984 bytes)
578
579
=== Invalid sizes ===
580
581
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
582
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
583
{"return": {}}
584
Job failed: Image size must be a multiple of 512 bytes
585
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
586
{"return": {}}
587
588
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
589
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
590
{"return": {}}
591
Job failed: Image size is too large for this cluster size
592
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
593
{"return": {}}
594
595
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
596
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
597
{"return": {}}
598
Job failed: Image size is too large for this cluster size
599
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
600
{"return": {}}
601
602
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
603
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
604
{"return": {}}
605
Job failed: Image size is too large for this cluster size
606
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
607
{"return": {}}
608
609
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
610
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
611
{"return": {}}
612
Job failed: Image size is too large for this cluster size
613
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
614
@@ -XXX,XX +XXX,XX @@ Job failed: Image size is too large for this cluster size
615
616
=== Invalid cluster size ===
617
618
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
619
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
620
{"return": {}}
621
Job failed: Cluster size must be a multiple of 512 bytes
622
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
623
{"return": {}}
624
625
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
626
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
627
{"return": {}}
628
Job failed: Cluster size must be a multiple of 512 bytes
629
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
630
{"return": {}}
631
632
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
633
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
634
{"return": {}}
635
Job failed: Cluster size is too large
636
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
637
{"return": {}}
638
639
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
640
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
641
{"return": {}}
642
Job failed: Cluster size is too large
643
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
644
{"return": {}}
645
646
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
647
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
648
{"return": {}}
649
Job failed: Cluster size is too large
650
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
651
{"return": {}}
652
653
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
654
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
655
{"return": {}}
656
Job failed: Image size is too large for this cluster size
657
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
658
{"return": {}}
659
660
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
661
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
662
{"return": {}}
663
Job failed: Image size is too large for this cluster size
664
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
665
diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
666
index XXXXXXX..XXXXXXX 100644
667
--- a/tests/qemu-iotests/213.out
668
+++ b/tests/qemu-iotests/213.out
669
@@ -XXX,XX +XXX,XX @@
670
=== Successful image creation (defaults) ===
671
672
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
673
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
674
{"return": {}}
675
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
676
{"return": {}}
677
678
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}}
679
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node-name": "imgfile"}}
680
{"return": {}}
681
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
682
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
683
{"return": {}}
684
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
685
{"return": {}}
686
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
687
688
=== Successful image creation (explicit defaults) ===
689
690
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
691
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
692
{"return": {}}
693
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
694
{"return": {}}
695
696
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
697
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
698
{"return": {}}
699
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
700
{"return": {}}
701
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
702
703
=== Successful image creation (with non-default options) ===
704
705
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
706
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
707
{"return": {}}
708
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
709
{"return": {}}
710
711
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
712
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
713
{"return": {}}
714
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
715
{"return": {}}
716
@@ -XXX,XX +XXX,XX @@ cluster_size: 268435456
717
718
=== Invalid BlockdevRef ===
719
720
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
721
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
722
{"return": {}}
723
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
724
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
725
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
726
727
=== Zero size ===
728
729
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
730
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
731
{"return": {}}
732
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
733
{"return": {}}
734
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
735
736
=== Maximum size ===
737
738
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
739
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
740
{"return": {}}
741
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
742
{"return": {}}
743
@@ -XXX,XX +XXX,XX @@ cluster_size: 67108864
744
745
=== Invalid sizes ===
746
747
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
748
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
749
{"return": {}}
750
Job failed: Image size too large; max of 64TB
751
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
752
{"return": {}}
753
754
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
755
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
756
{"return": {}}
757
Job failed: Image size too large; max of 64TB
758
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
759
{"return": {}}
760
761
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
762
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
763
{"return": {}}
764
Job failed: Image size too large; max of 64TB
765
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
766
{"return": {}}
767
768
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
769
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
770
{"return": {}}
771
Job failed: Image size too large; max of 64TB
772
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
773
@@ -XXX,XX +XXX,XX @@ Job failed: Image size too large; max of 64TB
774
775
=== Invalid block size ===
776
777
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
778
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
779
{"return": {}}
780
Job failed: Block size must be a multiple of 1 MB
781
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
782
{"return": {}}
783
784
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
785
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
786
{"return": {}}
787
Job failed: Block size must be a multiple of 1 MB
788
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
789
{"return": {}}
790
791
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
792
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
793
{"return": {}}
794
Job failed: Block size must be a power of two
795
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
796
{"return": {}}
797
798
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
799
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
800
{"return": {}}
801
Job failed: Block size must not exceed 268435456
802
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
803
{"return": {}}
804
805
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
806
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
807
{"return": {}}
808
Job failed: Block size must be a multiple of 1 MB
809
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
810
@@ -XXX,XX +XXX,XX @@ Job failed: Block size must be a multiple of 1 MB
811
812
=== Invalid log size ===
813
814
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
815
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
816
{"return": {}}
817
Job failed: Log size must be a multiple of 1 MB
818
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
819
{"return": {}}
820
821
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
822
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
823
{"return": {}}
824
Job failed: Log size must be a multiple of 1 MB
825
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
826
{"return": {}}
827
828
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
829
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
830
{"return": {}}
831
Job failed: Log size must be smaller than 4 GB
832
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
833
{"return": {}}
834
835
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
836
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
837
{"return": {}}
838
Job failed: Log size must be a multiple of 1 MB
839
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
840
diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out
841
index XXXXXXX..XXXXXXX 100644
842
--- a/tests/qemu-iotests/237.out
843
+++ b/tests/qemu-iotests/237.out
844
@@ -XXX,XX +XXX,XX @@
845
=== Successful image creation (defaults) ===
846
847
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
848
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
849
{"return": {}}
850
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
851
{"return": {}}
852
853
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}}
854
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node-name": "imgfile"}}
855
{"return": {}}
856
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
857
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
858
{"return": {}}
859
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
860
{"return": {}}
861
@@ -XXX,XX +XXX,XX @@ Format specific information:
862
863
=== Successful image creation (inline blockdev-add, explicit defaults) ===
864
865
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
866
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
867
{"return": {}}
868
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
869
{"return": {}}
870
871
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
872
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
873
{"return": {}}
874
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
875
{"return": {}}
876
@@ -XXX,XX +XXX,XX @@ Format specific information:
877
878
=== Successful image creation (with non-default options) ===
879
880
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
881
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
882
{"return": {}}
883
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
884
{"return": {}}
885
886
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
887
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
888
{"return": {}}
889
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
890
{"return": {}}
891
@@ -XXX,XX +XXX,XX @@ Format specific information:
892
893
=== Invalid BlockdevRef ===
894
895
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
896
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
897
{"return": {}}
898
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
899
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
900
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
901
902
== Valid adapter types ==
903
904
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
905
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
906
{"return": {}}
907
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
908
{"return": {}}
909
910
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
911
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
912
{"return": {}}
913
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
914
{"return": {}}
915
916
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
917
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
918
{"return": {}}
919
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
920
{"return": {}}
921
922
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
923
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
924
{"return": {}}
925
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
926
{"return": {}}
927
928
== Invalid adapter types ==
929
930
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
931
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
932
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
933
934
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
935
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
936
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
937
938
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
939
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
940
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
941
942
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
943
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
944
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
945
946
=== Other subformats ===
947
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/PID-t.vmdk.3', fmt=vmdk size=0 compat6=off hwversion=undefi
948
949
== Missing extent ==
950
951
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
952
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
953
{"return": {}}
954
Job failed: Extent [0] not specified
955
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
956
@@ -XXX,XX +XXX,XX @@ Job failed: Extent [0] not specified
957
958
== Correct extent ==
959
960
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
961
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
962
{"return": {}}
963
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
964
{"return": {}}
965
966
== Extra extent ==
967
968
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
969
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
970
{"return": {}}
971
Job failed: List of extents contains unused extents
972
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
973
@@ -XXX,XX +XXX,XX @@ Job failed: List of extents contains unused extents
974
975
= twoGbMaxExtentFlat 512 =
976
977
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
978
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
979
{"return": {}}
980
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
981
{"return": {}}
982
@@ -XXX,XX +XXX,XX @@ Format specific information:
983
984
= twoGbMaxExtentSparse 512 =
985
986
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
987
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
988
{"return": {}}
989
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
990
{"return": {}}
991
@@ -XXX,XX +XXX,XX @@ Format specific information:
992
993
= twoGbMaxExtentFlat 1073741824 =
994
995
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
996
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
997
{"return": {}}
998
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
999
{"return": {}}
1000
@@ -XXX,XX +XXX,XX @@ Format specific information:
1001
1002
= twoGbMaxExtentSparse 1073741824 =
1003
1004
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
1005
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
1006
{"return": {}}
1007
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1008
{"return": {}}
1009
@@ -XXX,XX +XXX,XX @@ Format specific information:
1010
1011
= twoGbMaxExtentFlat 2147483648 =
1012
1013
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
1014
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
1015
{"return": {}}
1016
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1017
{"return": {}}
1018
@@ -XXX,XX +XXX,XX @@ Format specific information:
1019
1020
= twoGbMaxExtentSparse 2147483648 =
1021
1022
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
1023
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
1024
{"return": {}}
1025
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1026
{"return": {}}
1027
@@ -XXX,XX +XXX,XX @@ Format specific information:
1028
1029
= twoGbMaxExtentFlat 5368709120 =
1030
1031
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
1032
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
1033
{"return": {}}
1034
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1035
{"return": {}}
1036
@@ -XXX,XX +XXX,XX @@ Format specific information:
1037
1038
= twoGbMaxExtentSparse 5368709120 =
1039
1040
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
1041
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
1042
{"return": {}}
1043
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1044
{"return": {}}
1045
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
1046
index XXXXXXX..XXXXXXX 100644
1047
--- a/tests/qemu-iotests/iotests.py
1048
+++ b/tests/qemu-iotests/iotests.py
1049
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args):
1050
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
1051
return exitcode
1052
1053
-def ordered_qmp(qmsg):
1054
+def ordered_qmp(qmsg, conv_keys=True):
1055
# Dictionaries are not ordered prior to 3.6, therefore:
1056
if isinstance(qmsg, list):
1057
return [ordered_qmp(atom) for atom in qmsg]
1058
if isinstance(qmsg, dict):
1059
od = OrderedDict()
1060
for k, v in sorted(qmsg.items()):
1061
- od[k] = ordered_qmp(v)
1062
+ if conv_keys:
1063
+ k = k.replace('_', '-')
1064
+ od[k] = ordered_qmp(v, conv_keys=False)
1065
return od
1066
return qmsg
1067
1068
--
1069
2.20.1
1070
1071
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
The previous patch includes the LUKS payload overhead into the qemu-img
4
measure calculation for qcow2. Update qemu-iotests 178 to exercise this
5
new code path.
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20190218104525.23674-3-stefanha@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/178 | 8 ++++++++
14
tests/qemu-iotests/178.out.qcow2 | 24 ++++++++++++++++++++++++
15
2 files changed, 32 insertions(+)
16
17
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/178
20
+++ b/tests/qemu-iotests/178
21
@@ -XXX,XX +XXX,XX @@ for ofmt in human json; do
22
# The backing file doesn't need to exist :)
23
$QEMU_IMG measure --output=$ofmt -o backing_file=x \
24
-f "$fmt" -O "$IMGFMT" "$TEST_IMG"
25
+
26
+ echo
27
+ echo "== $fmt input image and LUKS encryption =="
28
+ echo
29
+ $QEMU_IMG measure --output=$ofmt \
30
+ --object secret,id=sec0,data=base \
31
+ -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10 \
32
+ -f "$fmt" -O "$IMGFMT" "$TEST_IMG"
33
fi
34
35
echo
36
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/178.out.qcow2
39
+++ b/tests/qemu-iotests/178.out.qcow2
40
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 458752
41
required size: 1074135040
42
fully allocated size: 1074135040
43
44
+== qcow2 input image and LUKS encryption ==
45
+
46
+required size: 2686976
47
+fully allocated size: 1076232192
48
+
49
== qcow2 input image and preallocation (human) ==
50
51
required size: 1074135040
52
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 524288
53
required size: 1074135040
54
fully allocated size: 1074135040
55
56
+== raw input image and LUKS encryption ==
57
+
58
+required size: 2686976
59
+fully allocated size: 1076232192
60
+
61
== raw input image and preallocation (human) ==
62
63
required size: 1074135040
64
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 458752
65
"fully-allocated": 1074135040
66
}
67
68
+== qcow2 input image and LUKS encryption ==
69
+
70
+{
71
+ "required": 2686976,
72
+ "fully-allocated": 1076232192
73
+}
74
+
75
== qcow2 input image and preallocation (json) ==
76
77
{
78
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 524288
79
"fully-allocated": 1074135040
80
}
81
82
+== raw input image and LUKS encryption ==
83
+
84
+{
85
+ "required": 2686976,
86
+ "fully-allocated": 1076232192
87
+}
88
+
89
== raw input image and preallocation (json) ==
90
91
{
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
From: yuchenlin <yuchenlin@synology.com>
2
1
3
In vmdk_co_create_opts, when it finds hw_version is undefined, it will
4
set it to 4, which misleading the compat6 and hwversion in
5
vmdk_co_do_create. Simply set hw_version to NULL after free, let
6
the logic in vmdk_co_do_create to decide the value of hw_version.
7
8
This bug can be reproduced by:
9
10
$ qemu-img convert -O vmdk -o subformat=streamOptimized,compat6
11
/home/yuchenlin/syno.qcow2 /home/yuchenlin/syno.vmdk
12
13
qemu-img: /home/yuchenlin/syno.vmdk: error while converting vmdk:
14
compat6 cannot be enabled with hwversion set
15
16
Signed-off-by: yuchenlin <yuchenlin@synology.com>
17
Message-id: 20190221110805.28239-1-yuchenlin@synology.com
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block/vmdk.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
22
23
diff --git a/block/vmdk.c b/block/vmdk.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/vmdk.c
26
+++ b/block/vmdk.c
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
28
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
29
if (strcmp(hw_version, "undefined") == 0) {
30
g_free(hw_version);
31
- hw_version = g_strdup("4");
32
+ hw_version = NULL;
33
}
34
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
35
zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
VDI keeps the whole bitmap in memory, and the maximum size (which is
4
tested here) is 2 GB. This may not be available on all machines, and it
5
rarely is available when running a 32 bit build.
6
7
Fix this by making VM.run_job() return the error string if an error
8
occurred, and checking whether that contains "Could not allocate bmap"
9
in 211. If so, the test is skipped.
10
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20190218180646.30282-1-mreitz@redhat.com
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/211 | 4 +++-
18
tests/qemu-iotests/iotests.py | 5 ++++-
19
2 files changed, 7 insertions(+), 2 deletions(-)
20
21
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/211
24
+++ b/tests/qemu-iotests/211
25
@@ -XXX,XX +XXX,XX @@ def blockdev_create(vm, options):
26
27
if 'return' in result:
28
assert result['return'] == {}
29
- vm.run_job('job0')
30
+ error = vm.run_job('job0')
31
+ if error and 'Could not allocate bmap' in error:
32
+ iotests.notrun('Insufficient memory')
33
iotests.log("")
34
35
with iotests.FilePath('t.vdi') as disk_path, \
36
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/iotests.py
39
+++ b/tests/qemu-iotests/iotests.py
40
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
41
log(result, filters, indent=indent)
42
return result
43
44
+ # Returns None on success, and an error string on failure
45
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
46
+ error = None
47
while True:
48
for ev in self.get_qmp_events_filtered(wait=True):
49
if ev['event'] == 'JOB_STATUS_CHANGE':
50
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
51
result = self.qmp('query-jobs')
52
for j in result['return']:
53
if j['id'] == job:
54
+ error = j['error']
55
log('Job failed: %s' % (j['error']))
56
elif status == 'pending' and not auto_finalize:
57
self.qmp_log('job-finalize', id=job)
58
elif status == 'concluded' and not auto_dismiss:
59
self.qmp_log('job-dismiss', id=job)
60
elif status == 'null':
61
- return
62
+ return error
63
else:
64
iotests.log(ev)
65
66
--
67
2.20.1
68
69
diff view generated by jsdifflib