1
The following changes since commit 59a568b57848b10e8a44518a889323f12ccdd8f4:
1
The following changes since commit 344744e148e6e865f5a57e745b02a87e5ea534ad:
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 tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging (2022-10-26 10:53:49 -0400)
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 be8da05b5ed8fb546731b9edb997f303f272bad8:
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
block/block-backend: blk_set_enable_write_cache is IO_CODE (2022-10-27 20:27:37 +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
- Cleanup bs->backing and bs->file handling
17
- bdrv_set_aio_context() related fixes
17
- Refactor bdrv_try_set_aio_context using transactions
18
- HMP snapshot commands: Use only tag, not the ID to identify snapshots
18
- Changes for improved coroutine_fn consistency
19
- qmeu-img, commit: Error path fixes
19
- vhost-user-blk: fix the resize crash
20
- block/nvme: Build fix for gcc 9
20
- io_uring: Use of io_uring_register_ring_fd() led to breakage, revert
21
- MAINTAINERS updates
21
- vvfat: Fix some problems with r/w mode
22
- Fix various issues with bdrv_refresh_filename()
22
- Code cleanup
23
- Fix various iotests
23
- MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
24
- Include LUKS overhead in qemu-img measure for qcow2
25
- A fix for vmdk's image creation interface
26
24
27
----------------------------------------------------------------
25
----------------------------------------------------------------
28
Alberto Garcia (2):
26
Alberto Faria (20):
29
commit: Replace commit_top_bs on failure after deleting the block job
27
backup: remove incorrect coroutine_fn annotation
30
qcow2: Assert that L2 table offsets fit in the L1 table
28
block: remove incorrect coroutine_fn annotation
29
monitor: add missing coroutine_fn annotation
30
ssh: add missing coroutine_fn annotation
31
block: add missing coroutine_fn annotation to prototypes
32
coroutine-lock: add missing coroutine_fn annotation to prototypes
33
coroutine-io: add missing coroutine_fn annotation to prototypes
34
block: add missing coroutine_fn annotation to BlockDriverState callbacks
35
qcow2: add coroutine_fn annotation for indirect-called functions
36
commit: switch to *_co_* functions
37
block: switch to *_co_* functions
38
mirror: switch to *_co_* functions
39
parallels: switch to *_co_* functions
40
qcow: switch to *_co_* functions
41
qcow2: switch to *_co_* functions
42
qed: switch to *_co_* functions
43
vdi: switch to *_co_* functions
44
vhdx: switch to *_co_* functions
45
vmdk: switch to *_co_* functions
46
monitor: switch to *_co_* functions
31
47
32
Daniel Henrique Barboza (3):
48
Bin Meng (3):
33
block/snapshot.c: eliminate use of ID input in snapshot operations
49
block: Ignore close() failure in get_tmp_filename()
34
block/snapshot: remove bdrv_snapshot_delete_by_id_or_name
50
block: Refactor get_tmp_filename()
35
qcow2-snapshot: remove redundant find_snapshot_by_id_and_name call
51
block/nfs: Fix 32-bit Windows build
36
52
37
Daniel P. Berrangé (1):
53
Emanuele Giuseppe Esposito (11):
38
qemu-img: fix error reporting for -object
54
block.c: assert bs->aio_context is written under BQL and drains
55
block: use transactions as a replacement of ->{can_}set_aio_context()
56
bdrv_change_aio_context: use hash table instead of list of visited nodes
57
blockjob: implement .change_aio_ctx in child_job
58
block: implement .change_aio_ctx in child_of_bds
59
block-backend: implement .change_aio_ctx in child_root
60
block: use the new _change_ API instead of _can_set_ and _set_
61
block: remove all unused ->can_set_aio_ctx and ->set_aio_ctx callbacks
62
block: rename bdrv_child_try_change_aio_context in bdrv_try_change_aio_context
63
block: remove bdrv_try_set_aio_context and replace it with bdrv_try_change_aio_context
64
block/block-backend: blk_set_enable_write_cache is IO_CODE
39
65
40
Denis Plotnikov (1):
66
Hervé Poussineau (2):
41
block: don't set the same context
67
vvfat: allow some writes to bootsector
68
vvfat: allow spaces in file names
42
69
43
Jeff Cody (2):
70
Li Feng (1):
44
MAINTAINERS: Replace myself with John Snow for block jobs
71
vhost-user-blk: fix the resize crash
45
MAINTAINERS: Remove myself as block maintainer
46
72
47
Kevin Wolf (14):
73
Markus Armbruster (1):
48
block-backend: Make blk_inc/dec_in_flight public
74
MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
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
75
63
Max Reitz (42):
76
Paolo Bonzini (4):
64
block: Use bdrv_refresh_filename() to pull
77
blkdebug: add missing coroutine_fn annotation for indirect-called functions
65
block: Use children list in bdrv_refresh_filename
78
qcow: manually add more coroutine_fn annotations
66
block: Skip implicit nodes for filename info
79
qcow2: manually add more coroutine_fn annotations
67
block: Add BDS.auto_backing_file
80
vmdk: manually add more coroutine_fn annotations
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
81
107
Stefan Hajnoczi (2):
82
Sam Li (1):
108
qcow2: include LUKS payload overhead in qemu-img measure
83
block/io_uring: revert "Use io_uring_register_ring_fd() to skip fd operations"
109
iotests: add LUKS payload overhead to 178 qemu-img measure test
110
84
111
Thomas Huth (1):
85
Vladimir Sementsov-Ogievskiy (15):
112
block/nvme: Remove QEMU_PACKED from naturally aligned NVMeRegs struct
86
block: BlockDriver: add .filtered_child_is_backing field
87
block: introduce bdrv_open_file_child() helper
88
block/blklogwrites: don't care to remove bs->file child on failure
89
test-bdrv-graph-mod: update test_parallel_perm_update test case
90
tests-bdrv-drain: bdrv_replace_test driver: declare supports_backing
91
test-bdrv-graph-mod: fix filters to be filters
92
block: document connection between child roles and bs->backing/bs->file
93
block/snapshot: stress that we fallback to primary child
94
Revert "block: Let replace_child_noperm free children"
95
Revert "block: Let replace_child_tran keep indirect pointer"
96
Revert "block: Restructure remove_file_or_backing_child()"
97
Revert "block: Pass BdrvChild ** to replace_child_noperm"
98
block: Manipulate bs->file / bs->backing pointers in .attach/.detach
99
block/snapshot: drop indirection around bdrv_snapshot_fallback_ptr
100
block: refactor bdrv_remove_file_or_backing_child to bdrv_remove_child
113
101
114
Vladimir Sementsov-Ogievskiy (3):
102
docs/devel/multiple-iothreads.txt | 4 +-
115
block: improve should_update_child
103
block/qcow2.h | 32 +-
116
block: fix bdrv_check_perm for non-tree subgraph
104
include/block/block-common.h | 39 ++
117
tests: add test-bdrv-graph-mod
105
include/block/block-global-state.h | 18 +-
106
include/block/block-hmp-cmds.h | 2 +-
107
include/block/block-io.h | 5 +-
108
include/block/block_int-common.h | 49 ++-
109
include/monitor/hmp.h | 3 +-
110
include/qemu/coroutine.h | 18 +-
111
block.c | 855 +++++++++++++++++--------------------
112
block/backup.c | 2 +-
113
block/blkdebug.c | 11 +-
114
block/blklogwrites.c | 11 +-
115
block/blkreplay.c | 7 +-
116
block/blkverify.c | 9 +-
117
block/block-backend.c | 76 ++--
118
block/bochs.c | 7 +-
119
block/cloop.c | 7 +-
120
block/commit.c | 3 +-
121
block/copy-before-write.c | 9 +-
122
block/copy-on-read.c | 9 +-
123
block/crypto.c | 11 +-
124
block/dmg.c | 7 +-
125
block/export/export.c | 2 +-
126
block/filter-compress.c | 8 +-
127
block/io.c | 8 +-
128
block/io_uring.c | 13 +-
129
block/mirror.c | 5 +-
130
block/monitor/block-hmp-cmds.c | 2 +-
131
block/nfs.c | 8 +
132
block/parallels.c | 35 +-
133
block/preallocate.c | 9 +-
134
block/qcow.c | 66 +--
135
block/qcow2-bitmap.c | 4 +-
136
block/qcow2-cluster.c | 29 +-
137
block/qcow2-refcount.c | 18 +-
138
block/qcow2-snapshot.c | 6 +-
139
block/qcow2.c | 40 +-
140
block/qed-table.c | 2 +-
141
block/qed.c | 20 +-
142
block/raw-format.c | 4 +-
143
block/replication.c | 8 +-
144
block/snapshot-access.c | 6 +-
145
block/snapshot.c | 59 +--
146
block/ssh.c | 6 +-
147
block/throttle.c | 8 +-
148
block/vdi.c | 24 +-
149
block/vhdx.c | 15 +-
150
block/vmdk.c | 95 ++---
151
block/vpc.c | 7 +-
152
block/vvfat.c | 35 +-
153
blockdev.c | 24 +-
154
blockjob.c | 50 ++-
155
hw/block/vhost-user-blk.c | 4 +
156
job.c | 2 +-
157
tests/unit/test-bdrv-drain.c | 17 +-
158
tests/unit/test-bdrv-graph-mod.c | 104 +++--
159
tests/unit/test-block-iothread.c | 10 +-
160
MAINTAINERS | 12 +-
161
meson.build | 1 -
162
tests/qemu-iotests/051 | 3 +-
163
tests/qemu-iotests/051.out | 2 +-
164
tests/qemu-iotests/051.pc.out | 2 +-
165
63 files changed, 984 insertions(+), 983 deletions(-)
118
166
119
yuchenlin (1):
120
vmdk: false positive of compat6 with hwversion not set
121
167
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
1
From: Jeff Cody <jcody@redhat.com>
1
From: Markus Armbruster <armbru@redhat.com>
2
2
3
I'll not be involved in day-to-day qemu development. Remove myself as
3
Section "Block QAPI, monitor, command line" is about the external
4
maintainer from the remainder of the network block drivers, and revert
4
interfaces we provide for block devices. It covers the relevant QAPI
5
them to the general block layer maintainership.
5
schema parts, monitor and command line code, more or less.
6
6
7
Move 'sheepdog' to the 'Odd Fixes' support level.
7
The section's files are also covered by section "Block layer core",
8
except for the QAPI schema files.
8
9
9
For VHDX, added my personal email address as a maintainer, as I can
10
I haven't acted as maintainer in this area for a long time. Make it
10
answer questions or send the occassional bug fix. Leaving it as
11
official: add the QAPI schema files to section "Block layer core", and
11
'Supported', instead of 'Odd Fixes', because I think the rest of the
12
delete section "Block QAPI, monitor, command line".
12
block layer maintainers and developers will upkeep it as well, if
13
needed.
14
13
15
Signed-off-by: Jeff Cody <jcody@redhat.com>
14
Cc: Kevin Wolf <kwolf@redhat.com>
16
Acked-by: Max Reitz <mreitz@redhat.com>
15
Cc: Hanna Reitz <hreitz@redhat.com>
17
Message-Id: <63e205cb84c8f0a10c1bc6d5d6856d72ceb56e41.1537984851.git.jcody@redhat.com>
16
Signed-off-by: Markus Armbruster <armbru@redhat.com>
17
Message-Id: <20221020120541.80757-1-armbru@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
---
20
MAINTAINERS | 18 +++---------------
21
MAINTAINERS | 12 ++----------
21
1 file changed, 3 insertions(+), 15 deletions(-)
22
1 file changed, 2 insertions(+), 10 deletions(-)
22
23
23
diff --git a/MAINTAINERS b/MAINTAINERS
24
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/MAINTAINERS
26
--- a/MAINTAINERS
26
+++ b/MAINTAINERS
27
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ F: block/vmdk.c
28
@@ -XXX,XX +XXX,XX @@ S: Supported
28
29
F: block*
29
RBD
30
F: block/
30
M: Josh Durgin <jdurgin@redhat.com>
31
F: hw/block/
31
-M: Jeff Cody <jcody@redhat.com>
32
+F: qapi/block*.json
32
L: qemu-block@nongnu.org
33
+F: qapi/transaction.json
33
S: Supported
34
F: include/block/
34
F: block/rbd.c
35
F: qemu-img*
35
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
36
F: docs/tools/qemu-img.rst
36
37
@@ -XXX,XX +XXX,XX @@ F: include/qemu/co-shared-resource.h
37
Sheepdog
38
T: git https://gitlab.com/jsnow/qemu.git jobs
38
M: Liu Yuan <namei.unix@gmail.com>
39
T: git https://gitlab.com/vsementsov/qemu.git block
39
-M: Jeff Cody <jcody@redhat.com>
40
40
L: qemu-block@nongnu.org
41
-Block QAPI, monitor, command line
42
-M: Markus Armbruster <armbru@redhat.com>
41
-S: Supported
43
-S: Supported
42
+L: sheepdog@lists.wpkg.org
44
-F: blockdev.c
43
+S: Odd Fixes
45
-F: blockdev-hmp-cmds.c
44
F: block/sheepdog.c
46
-F: block/qapi.c
45
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
47
-F: qapi/block*.json
46
48
-F: qapi/transaction.json
47
VHDX
49
-T: git https://repo.or.cz/qemu/armbru.git block-next
48
-M: Jeff Cody <jcody@redhat.com>
50
-
49
+M: Jeff Cody <codyprime@gmail.com>
51
Compute Express Link
50
L: qemu-block@nongnu.org
52
M: Ben Widawsky <ben.widawsky@intel.com>
51
S: Supported
53
M: Jonathan Cameron <jonathan.cameron@huawei.com>
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
--
54
--
93
2.20.1
55
2.37.3
94
95
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
If a format BDS's file BDS is in turn a format BDS, we cannot simply use
3
The temporary file has been created and is ready for use. Checking
4
the same filename, because when opening a BDS tree based on a filename
4
return value of close() does not seem useful. The file descriptor
5
alone, qemu will create only one format node on top of one protocol node
5
is almost certainly closed; see close(2) under "Dealing with error
6
(disregarding a potential backing file).
6
returns from close()".
7
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Let's simply ignore close() failure here.
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
10
Message-id: 20190201192935.18394-26-mreitz@redhat.com
10
Suggested-by: Markus Armbruster <armbru@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
13
Message-Id: <20221010040432.3380478-1-bin.meng@windriver.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
16
---
13
block.c | 18 +++++++++++++++---
17
block.c | 5 +----
14
1 file changed, 15 insertions(+), 3 deletions(-)
18
1 file changed, 1 insertion(+), 4 deletions(-)
15
19
16
diff --git a/block.c b/block.c
20
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
22
--- a/block.c
19
+++ b/block.c
23
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
24
@@ -XXX,XX +XXX,XX @@ int get_tmp_filename(char *filename, int size)
21
25
if (fd < 0) {
22
bs->exact_filename[0] = '\0';
26
return -errno;
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
}
27
}
28
- if (close(fd) != 0) {
29
- unlink(filename);
30
- return -errno;
31
- }
32
+ close(fd);
33
return 0;
34
#endif
35
}
45
--
36
--
46
2.20.1
37
2.37.3
47
48
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
Basically, bdrv_refresh_filename() should respect all children of a
3
At present there are two callers of get_tmp_filename() and they are
4
BlockDriverState. However, generally those children are driver-specific,
4
inconsistent.
5
so this function cannot handle the general case. On the other hand,
5
6
there are only few drivers which use other children than @file and
6
One does:
7
@backing (that being vmdk, quorum, and blkverify).
7
8
8
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
9
Most block drivers only use @file and/or @backing (if they use any
9
char *tmp_filename = g_malloc0(PATH_MAX + 1);
10
children at all). Both can be implemented directly in
10
...
11
bdrv_refresh_filename.
11
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
12
12
13
The user overriding the file's filename is already handled, however, the
13
while the other does:
14
user overriding the backing file is not. If this is done, opening the
14
15
BDS with the plain filename of its file will not be correct, so we may
15
s->qcow_filename = g_malloc(PATH_MAX);
16
not set bs->exact_filename in that case.
16
ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
17
17
18
iotest 051 contains test cases for overriding the backing file, and so
18
As we can see different 'size' arguments are passed. There are also
19
its output changes with this patch applied.
19
platform specific implementations inside the function, and the use
20
20
of snprintf is really undesirable.
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
The function name is also misleading. It creates a temporary file,
23
Message-id: 20190201192935.18394-6-mreitz@redhat.com
23
not just a filename.
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
25
Refactor this routine by changing its name and signature to:
26
27
char *create_tmp_file(Error **errp)
28
29
and use g_get_tmp_dir() / g_mkstemp() for a consistent implementation.
30
31
While we are here, add some comments to mention that /var/tmp is
32
preferred over /tmp on non-win32 hosts.
33
34
Signed-off-by: Bin Meng <bin.meng@windriver.com>
35
Message-Id: <20221010040432.3380478-2-bin.meng@windriver.com>
36
[kwolf: Fixed incorrect errno negation and iotest 051]
37
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
39
---
26
block.c | 38 ++++++++++++++++++++++++++++++++++-
40
include/block/block_int-common.h | 2 +-
27
tests/qemu-iotests/051.out | 8 ++++----
41
block.c | 56 +++++++++++++++++---------------
28
tests/qemu-iotests/051.pc.out | 8 ++++----
42
block/vvfat.c | 7 ++--
29
3 files changed, 45 insertions(+), 9 deletions(-)
43
tests/qemu-iotests/051 | 3 +-
30
44
tests/qemu-iotests/051.out | 2 +-
45
tests/qemu-iotests/051.pc.out | 2 +-
46
6 files changed, 38 insertions(+), 34 deletions(-)
47
48
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block_int-common.h
51
+++ b/include/block/block_int-common.h
52
@@ -XXX,XX +XXX,XX @@ static inline BlockDriverState *child_bs(BdrvChild *child)
53
}
54
55
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp);
56
-int get_tmp_filename(char *filename, int size);
57
+char *create_tmp_file(Error **errp);
58
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
59
QDict *options);
60
31
diff --git a/block.c b/block.c
61
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
63
--- a/block.c
34
+++ b/block.c
64
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
65
@@ -XXX,XX +XXX,XX @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
36
return found_any;
66
67
/*
68
* Create a uniquely-named empty temporary file.
69
- * Return 0 upon success, otherwise a negative errno value.
70
+ * Return the actual file name used upon success, otherwise NULL.
71
+ * This string should be freed with g_free() when not needed any longer.
72
+ *
73
+ * Note: creating a temporary file for the caller to (re)open is
74
+ * inherently racy. Use g_file_open_tmp() instead whenever practical.
75
*/
76
-int get_tmp_filename(char *filename, int size)
77
+char *create_tmp_file(Error **errp)
78
{
79
-#ifdef _WIN32
80
- char temp_dir[MAX_PATH];
81
- /* GetTempFileName requires that its output buffer (4th param)
82
- have length MAX_PATH or greater. */
83
- assert(size >= MAX_PATH);
84
- return (GetTempPath(MAX_PATH, temp_dir)
85
- && GetTempFileName(temp_dir, "qem", 0, filename)
86
- ? 0 : -GetLastError());
87
-#else
88
int fd;
89
const char *tmpdir;
90
- tmpdir = getenv("TMPDIR");
91
- if (!tmpdir) {
92
+ g_autofree char *filename = NULL;
93
+
94
+ tmpdir = g_get_tmp_dir();
95
+#ifndef _WIN32
96
+ /*
97
+ * See commit 69bef79 ("block: use /var/tmp instead of /tmp for -snapshot")
98
+ *
99
+ * This function is used to create temporary disk images (like -snapshot),
100
+ * so the files can become very large. /tmp is often a tmpfs where as
101
+ * /var/tmp is usually on a disk, so more appropriate for disk images.
102
+ */
103
+ if (!g_strcmp0(tmpdir, "/tmp")) {
104
tmpdir = "/var/tmp";
105
}
106
- if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
107
- return -EOVERFLOW;
108
- }
109
- fd = mkstemp(filename);
110
+#endif
111
+
112
+ filename = g_strdup_printf("%s/vl.XXXXXX", tmpdir);
113
+ fd = g_mkstemp(filename);
114
if (fd < 0) {
115
- return -errno;
116
+ error_setg_errno(errp, errno, "Could not open temporary file '%s'",
117
+ filename);
118
+ return NULL;
119
}
120
close(fd);
121
- return 0;
122
-#endif
123
+
124
+ return g_steal_pointer(&filename);
37
}
125
}
38
126
39
+/* Note: This function may return false positives; it may return true
127
/*
40
+ * even if opening the backing file specified by bs's image header
128
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
41
+ * would result in exactly bs->backing. */
129
QDict *snapshot_options,
42
+static bool bdrv_backing_overridden(BlockDriverState *bs)
130
Error **errp)
43
+{
131
{
44
+ if (bs->backing) {
132
- /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
45
+ return strcmp(bs->auto_backing_file,
133
- char *tmp_filename = g_malloc0(PATH_MAX + 1);
46
+ bs->backing->bs->filename);
134
+ g_autofree char *tmp_filename = NULL;
47
+ } else {
135
int64_t total_size;
48
+ /* No backing BDS, so if the image header reports any backing
136
QemuOpts *opts = NULL;
49
+ * file, it must have been suppressed */
137
BlockDriverState *bs_snapshot = NULL;
50
+ return bs->auto_backing_file[0] != '\0';
138
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
51
+ }
139
}
52
+}
140
53
+
141
/* Create the temporary image */
54
/* Updates the following BDS fields:
142
- ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
55
* - exact_filename: A filename which may be used for opening a block device
143
- if (ret < 0) {
56
* which (mostly) equals the given BDS (even without any
144
- error_setg_errno(errp, -ret, "Could not get temporary filename");
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
145
+ tmp_filename = create_tmp_file(errp);
58
BlockDriver *drv = bs->drv;
146
+ if (!tmp_filename) {
59
BdrvChild *child;
147
goto out;
60
QDict *opts;
148
}
61
+ bool backing_overridden;
149
62
150
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
63
if (!drv) {
151
64
return;
152
out:
65
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
153
qobject_unref(snapshot_options);
66
return;
154
- g_free(tmp_filename);
67
}
155
return bs_snapshot;
68
156
}
69
+ backing_overridden = bdrv_backing_overridden(bs);
157
70
+
158
diff --git a/block/vvfat.c b/block/vvfat.c
71
+ if (bs->open_flags & BDRV_O_NO_IO) {
159
index XXXXXXX..XXXXXXX 100644
72
+ /* Without I/O, the backing file does not change anything.
160
--- a/block/vvfat.c
73
+ * Therefore, in such a case (primarily qemu-img), we can
161
+++ b/block/vvfat.c
74
+ * pretend the backing file has not been overridden even if
162
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
75
+ * it technically has been. */
163
76
+ backing_overridden = false;
164
array_init(&(s->commits), sizeof(commit_t));
77
+ }
165
78
+
166
- s->qcow_filename = g_malloc(PATH_MAX);
79
if (drv->bdrv_refresh_filename) {
167
- ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
80
/* Obsolete information is of no use here, so drop the old file name
168
- if (ret < 0) {
81
* information before refreshing it */
169
- error_setg_errno(errp, -ret, "can't create temporary file");
82
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
170
+ s->qcow_filename = create_tmp_file(errp);
83
171
+ if (!s->qcow_filename) {
84
opts = qdict_new();
172
+ ret = -ENOENT;
85
has_open_options = append_open_options(opts, bs);
173
goto err;
86
+ has_open_options |= backing_overridden;
174
}
87
175
88
/* If no specific options have been given for this BDS, the filename of
176
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
89
* the underlying file should suffice for this one as well */
177
index XXXXXXX..XXXXXXX 100755
90
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
178
--- a/tests/qemu-iotests/051
91
* file BDS. The full options QDict of that file BDS should somehow
179
+++ b/tests/qemu-iotests/051
92
* contain a representation of the filename, therefore the following
180
@@ -XXX,XX +XXX,XX @@ if [ "${VALGRIND_QEMU_VM}" == "y" ]; then
93
* suffices without querying the (exact_)filename of this BDS. */
181
_casenotrun "Valgrind needs a valid TMPDIR for itself"
94
- if (bs->file->bs->full_open_options) {
182
fi
95
+ if (bs->file->bs->full_open_options &&
183
VALGRIND_QEMU_VM= \
96
+ (!bs->backing || bs->backing->bs->full_open_options))
184
-TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
97
+ {
185
+TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on |
98
qdict_put_str(opts, "driver", drv->format_name);
186
+ sed -e "s#'[^']*/vl\.[A-Za-z0-9]\{6\}'#SNAPSHOT_PATH#g"
99
qdict_put(opts, "file",
187
100
qobject_ref(bs->file->bs->full_open_options));
188
# Using snapshot=on together with read-only=on
101
189
echo "info block" |
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
190
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
113
index XXXXXXX..XXXXXXX 100644
191
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/qemu-iotests/051.out
192
--- a/tests/qemu-iotests/051.out
115
+++ b/tests/qemu-iotests/051.out
193
+++ b/tests/qemu-iotests/051.out
116
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
194
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
117
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
195
read 4096/4096 bytes at offset 0
196
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
Testing: -drive driver=null-co,snapshot=on
198
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
199
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
200
201
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
118
QEMU X.Y.Z monitor - type 'help' for more information
202
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
203
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
153
index XXXXXXX..XXXXXXX 100644
204
index XXXXXXX..XXXXXXX 100644
154
--- a/tests/qemu-iotests/051.pc.out
205
--- a/tests/qemu-iotests/051.pc.out
155
+++ b/tests/qemu-iotests/051.pc.out
206
+++ b/tests/qemu-iotests/051.pc.out
156
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
207
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
157
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
208
read 4096/4096 bytes at offset 0
209
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
210
Testing: -drive driver=null-co,snapshot=on
211
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
212
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
213
214
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
158
QEMU X.Y.Z monitor - type 'help' for more information
215
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
--
216
--
193
2.20.1
217
2.37.3
194
195
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
VDI keeps the whole bitmap in memory, and the maximum size (which is
3
'reserved1' field in bootsector is used to mark volume dirty, or need to verify.
4
tested here) is 2 GB. This may not be available on all machines, and it
4
Allow writes to bootsector which only changes the 'reserved1' field.
5
rarely is available when running a 32 bit build.
6
5
7
Fix this by making VM.run_job() return the error string if an error
6
This fixes I/O errors on Windows guests.
8
occurred, and checking whether that contains "Could not allocate bmap"
9
in 211. If so, the test is skipped.
10
7
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Resolves: https://bugs.launchpad.net/qemu/+bug/1889421
12
Message-id: 20190218180646.30282-1-mreitz@redhat.com
9
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20221010175511.3414357-2-hpoussin@reactos.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
13
---
17
tests/qemu-iotests/211 | 4 +++-
14
block/vvfat.c | 26 +++++++++++++++++++++++++-
18
tests/qemu-iotests/iotests.py | 5 ++++-
15
1 file changed, 25 insertions(+), 1 deletion(-)
19
2 files changed, 7 insertions(+), 2 deletions(-)
20
16
21
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
17
diff --git a/block/vvfat.c b/block/vvfat.c
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
18
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/iotests.py
19
--- a/block/vvfat.c
39
+++ b/tests/qemu-iotests/iotests.py
20
+++ b/block/vvfat.c
40
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
21
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
41
log(result, filters, indent=indent)
22
42
return result
23
vvfat_close_current_file(s);
43
24
44
+ # Returns None on success, and an error string on failure
25
+ if (sector_num == s->offset_to_bootsector && nb_sectors == 1) {
45
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
26
+ /*
46
+ error = None
27
+ * Write on bootsector. Allow only changing the reserved1 field,
47
while True:
28
+ * used to mark volume dirtiness
48
for ev in self.get_qmp_events_filtered(wait=True):
29
+ */
49
if ev['event'] == 'JOB_STATUS_CHANGE':
30
+ unsigned char *bootsector = s->first_sectors
50
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
31
+ + s->offset_to_bootsector * 0x200;
51
result = self.qmp('query-jobs')
32
+ /*
52
for j in result['return']:
33
+ * LATER TODO: if FAT32, this is wrong (see init_directories(),
53
if j['id'] == job:
34
+ * which always creates a FAT16 bootsector)
54
+ error = j['error']
35
+ */
55
log('Job failed: %s' % (j['error']))
36
+ const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
56
elif status == 'pending' and not auto_finalize:
37
+
57
self.qmp_log('job-finalize', id=job)
38
+ for (i = 0; i < 0x200; i++) {
58
elif status == 'concluded' and not auto_dismiss:
39
+ if (i != reserved1_offset && bootsector[i] != buf[i]) {
59
self.qmp_log('job-dismiss', id=job)
40
+ fprintf(stderr, "Tried to write to protected bootsector\n");
60
elif status == 'null':
41
+ return -1;
61
- return
42
+ }
62
+ return error
43
+ }
63
else:
44
+
64
iotests.log(ev)
45
+ /* Update bootsector with the only updatable byte, and return success */
46
+ bootsector[reserved1_offset] = buf[reserved1_offset];
47
+ return 0;
48
+ }
49
+
50
/*
51
* Some sanity checks:
52
* - do not allow writing to the boot sector
53
*/
54
-
55
if (sector_num < s->offset_to_fat)
56
return -1;
65
57
66
--
58
--
67
2.20.1
59
2.37.3
68
60
69
61
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
filter_qmp_testfiles() currently filters the filename only for specific
3
In R/W mode, files with spaces were never created on host side.
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
4
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1176
10
Reviewed-by: John Snow <jsnow@redhat.com>
6
Fixes: c79e243ed67683d6d06692bd7040f7394da178b0
11
Message-id: 20190210145736.1486-8-mreitz@redhat.com
7
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20221010175511.3414357-3-hpoussin@reactos.org>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
tests/qemu-iotests/iotests.py | 2 +-
13
block/vvfat.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
16
15
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
diff --git a/block/vvfat.c b/block/vvfat.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
18
--- a/block/vvfat.c
20
+++ b/tests/qemu-iotests/iotests.py
19
+++ b/block/vvfat.c
21
@@ -XXX,XX +XXX,XX @@ def filter_testfiles(msg):
20
@@ -XXX,XX +XXX,XX @@ static bool valid_filename(const unsigned char *name)
22
21
(c >= 'A' && c <= 'Z') ||
23
def filter_qmp_testfiles(qmsg):
22
(c >= 'a' && c <= 'z') ||
24
def _filter(key, value):
23
c > 127 ||
25
- if key == 'filename' or key == 'backing-file':
24
- strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
26
+ if is_str(value):
25
+ strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
27
return filter_testfiles(value)
26
{
28
return value
27
return false;
29
return filter_qmp(qmsg, _filter)
28
}
30
--
29
--
31
2.20.1
30
2.37.3
32
31
33
32
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
When BDSs are created by qemu itself (e.g. as filters in block jobs),
3
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1193
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
4
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
The commit "Use io_uring_register_ring_fd() to skip fd operations" broke
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
when booting a guest with iothread and io_uring. That is because the
9
Message-id: 20190201192935.18394-31-mreitz@redhat.com
7
io_uring_register_ring_fd() call is made from the main thread instead of
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
IOThread where io_uring_submit() is called. It can not be guaranteed
9
to register the ring fd in the correct thread or unregister the same ring
10
fd if the IOThread is disabled. This optimization is not critical so we
11
will revert previous commit.
12
13
This reverts commit e2848bc574fe2715c694bf8fe9a1ba7f78a1125a
14
and 77e3f038af1764983087e3551a0fde9951952c4d.
15
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Sam Li <faithilikerun@gmail.com>
18
Message-Id: <20220924144815.5591-1-faithilikerun@gmail.com>
19
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
20
Tested-by: Dario Faggioli <dfaggioli@suse.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
22
---
12
block.c | 6 ++++++
23
block/io_uring.c | 13 +------------
13
1 file changed, 6 insertions(+)
24
meson.build | 1 -
25
2 files changed, 1 insertion(+), 13 deletions(-)
14
26
15
diff --git a/block.c b/block.c
27
diff --git a/block/io_uring.c b/block/io_uring.c
16
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
29
--- a/block/io_uring.c
18
+++ b/block.c
30
+++ b/block/io_uring.c
19
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
31
@@ -XXX,XX +XXX,XX @@
20
}
32
#include "qemu/osdep.h"
33
#include <liburing.h>
34
#include "block/aio.h"
35
-#include "qemu/error-report.h"
36
#include "qemu/queue.h"
37
#include "block/block.h"
38
#include "block/raw-aio.h"
39
@@ -XXX,XX +XXX,XX @@
40
#include "qapi/error.h"
41
#include "trace.h"
42
43
-
44
/* io_uring ring size */
45
#define MAX_ENTRIES 128
46
47
@@ -XXX,XX +XXX,XX @@ LuringState *luring_init(Error **errp)
21
}
48
}
22
49
23
+ if (!qdict_haskey(d, "driver")) {
50
ioq_init(&s->io_q);
24
+ /* Drivers created with bdrv_new_open_driver() may not have a
51
-#ifdef CONFIG_LIBURING_REGISTER_RING_FD
25
+ * @driver option. Add it here. */
52
- if (io_uring_register_ring_fd(&s->ring) < 0) {
26
+ qdict_put_str(d, "driver", bs->drv->format_name);
53
- /*
27
+ }
54
- * Only warn about this error: we will fallback to the non-optimized
55
- * io_uring operations.
56
- */
57
- warn_report("failed to register linux io_uring ring file descriptor");
58
- }
59
-#endif
60
-
61
return s;
28
+
62
+
29
return found_any;
30
}
63
}
31
64
65
void luring_cleanup(LuringState *s)
66
diff --git a/meson.build b/meson.build
67
index XXXXXXX..XXXXXXX 100644
68
--- a/meson.build
69
+++ b/meson.build
70
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_LIBNFS', libnfs.found())
71
config_host_data.set('CONFIG_LIBSSH', libssh.found())
72
config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
73
config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
74
-config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
75
config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
76
config_host_data.set('CONFIG_NUMA', numa.found())
77
config_host_data.set('CONFIG_OPENGL', opengl.found())
32
--
78
--
33
2.20.1
79
2.37.3
34
35
diff view generated by jsdifflib
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
1
From: Li Feng <fengli@smartx.com>
2
2
3
Adds a fast path on aio context setting preventing
3
If the os is not installed and doesn't have the virtio guest driver,
4
unnecessary context setting routine.
4
the vhost dev isn't started, so the dev->vdev is NULL.
5
Also, it prevents issues with cyclic walk of child
6
bds-es appeared because of registering aio walking
7
notifiers:
8
5
9
Call stack:
6
Reproduce: mount a Win 2019 iso, go into the install ui, then resize
7
the virtio-blk device, qemu crash.
10
8
11
0 __GI_raise
9
Signed-off-by: Li Feng <fengli@smartx.com>
12
1 __GI_abort
10
Message-Id: <20220919121816.3252223-1-fengli@smartx.com>
13
2 __assert_fail_base
11
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
14
3 __GI___assert_fail
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
45
---
14
---
46
block.c | 4 ++++
15
hw/block/vhost-user-blk.c | 4 ++++
47
1 file changed, 4 insertions(+)
16
1 file changed, 4 insertions(+)
48
17
49
diff --git a/block.c b/block.c
18
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
50
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
51
--- a/block.c
20
--- a/hw/block/vhost-user-blk.c
52
+++ b/block.c
21
+++ b/hw/block/vhost-user-blk.c
53
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
22
@@ -XXX,XX +XXX,XX @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
54
{
23
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
55
AioContext *ctx = bdrv_get_aio_context(bs);
24
Error *local_err = NULL;
56
25
57
+ if (ctx == new_context) {
26
+ if (!dev->started) {
58
+ return;
27
+ return 0;
59
+ }
28
+ }
60
+
29
+
61
aio_disable_external(ctx);
30
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
62
bdrv_parent_drained_begin(bs, NULL, false);
31
vdev->config_len, &local_err);
63
bdrv_drain(bs); /* ensure there are no in-flight requests */
32
if (ret < 0) {
64
--
33
--
65
2.20.1
34
2.37.3
66
67
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
bdrv_refresh_filename() should invoke itself recursively on all
3
Unfortunately not all filters use .file child as filtered child. Two
4
children, not just on file.
4
exclusions are mirror_top and commit_top. Happily they both are private
5
filters. Bad thing is that this inconsistency is observable through qmp
6
commands query-block / query-named-block-nodes. So, could we just
7
change mirror_top and commit_top to use file child as all other filter
8
driver is an open question. Probably, we could do that with some kind
9
of deprecation period, but how to warn users during it?
5
10
6
With that change, we can remove the manual invocations in blkverify,
11
For now, let's just add a field so we can distinguish them in generic
7
quorum, commit, mirror, and blklogwrites.
12
code, it will be used in further commits.
8
13
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Message-Id: <20220726201134.924743-2-vsementsov@yandex-team.ru>
12
Message-id: 20190201192935.18394-3-mreitz@redhat.com
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
19
---
15
block.c | 9 +++++----
20
include/block/block_int-common.h | 13 +++++++++++++
16
block/blklogwrites.c | 3 ---
21
block/commit.c | 1 +
17
block/blkverify.c | 3 ---
22
block/mirror.c | 1 +
18
block/commit.c | 1 -
23
3 files changed, 15 insertions(+)
19
block/mirror.c | 1 -
20
block/quorum.c | 1 -
21
6 files changed, 5 insertions(+), 13 deletions(-)
22
24
23
diff --git a/block.c b/block.c
25
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
24
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
27
--- a/include/block/block_int-common.h
26
+++ b/block.c
28
+++ b/include/block/block_int-common.h
27
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
28
void bdrv_refresh_filename(BlockDriverState *bs)
30
* (And this filtered child must then be bs->file or bs->backing.)
29
{
31
*/
30
BlockDriver *drv = bs->drv;
32
bool is_filter;
31
+ BdrvChild *child;
33
+ /*
32
QDict *opts;
34
+ * Only make sense for filter drivers, for others must be false.
33
35
+ * If true, filtered child is bs->backing. Otherwise it's bs->file.
34
if (!drv) {
36
+ * Only two internal filters use bs->backing as filtered child and has this
35
return;
37
+ * field set to true: mirror_top and commit_top.
36
}
38
+ *
37
39
+ * Never create any more such filters!
38
- /* This BDS's file name will most probably depend on its file's name, so
40
+ *
39
- * refresh that first */
41
+ * TODO: imagine how to deprecate this behavior and make all filters work
40
- if (bs->file) {
42
+ * similarly using bs->file as filtered child.
41
- bdrv_refresh_filename(bs->file->bs);
43
+ */
42
+ /* This BDS's file name may depend on any of its children's file names, so
44
+ bool filtered_child_is_backing;
43
+ * refresh those first */
45
+
44
+ QLIST_FOREACH(child, &bs->children, next) {
46
/*
45
+ bdrv_refresh_filename(child->bs);
47
* Set to true if the BlockDriver is a format driver. Format nodes
46
}
48
* generally do not expect their children to be other format nodes
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
49
diff --git a/block/commit.c b/block/commit.c
78
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
79
--- a/block/commit.c
51
--- a/block/commit.c
80
+++ b/block/commit.c
52
+++ b/block/commit.c
81
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
53
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_commit_top = {
82
54
.bdrv_child_perm = bdrv_commit_top_child_perm,
83
static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
55
84
{
56
.is_filter = true,
85
- bdrv_refresh_filename(bs->backing->bs);
57
+ .filtered_child_is_backing = true,
86
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
58
};
87
bs->backing->bs->filename);
59
88
}
60
void commit_start(const char *job_id, BlockDriverState *bs,
89
diff --git a/block/mirror.c b/block/mirror.c
61
diff --git a/block/mirror.c b/block/mirror.c
90
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
91
--- a/block/mirror.c
63
--- a/block/mirror.c
92
+++ b/block/mirror.c
64
+++ b/block/mirror.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
65
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
94
* bdrv_set_backing_hd */
66
.bdrv_child_perm = bdrv_mirror_top_child_perm,
95
return;
67
96
}
68
.is_filter = true,
97
- bdrv_refresh_filename(bs->backing->bs);
69
+ .filtered_child_is_backing = true,
98
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
70
};
99
bs->backing->bs->filename);
71
100
}
72
static BlockJob *mirror_start_job(
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
--
73
--
114
2.20.1
74
2.37.3
115
116
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
This new field can be set by block drivers to list the runtime options
3
Almost all drivers call bdrv_open_child() similarly. Let's create a
4
they accept that may influence the contents of the respective BDS. As of
4
helper for this.
5
a follow-up patch, this list will be used by the common
6
bdrv_refresh_filename() implementation to decide which options to put
7
into BDS.full_open_options (and consequently whether a JSON filename has
8
to be created), thus freeing the drivers of having to implement that
9
logic themselves.
10
5
11
Additionally, this patch adds the field to all of the block drivers that
6
The only not updated drivers that call bdrv_open_child() to set
12
need it and sets it accordingly.
7
bs->file are raw-format and snapshot-access:
8
raw-format sometimes want to have filtered child but
9
don't set drv->is_filter to true.
10
snapshot-access wants only DATA | PRIMARY
13
11
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Possibly we should implement drv->is_filter_func() handler, to consider
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
13
raw-format as filter when it works as filter.. But it's another story.
16
Message-id: 20190201192935.18394-22-mreitz@redhat.com
14
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Note also, that we decrease assignments to bs->file in code: it helps
16
us restrict modifying this field in further commit.
17
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
19
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
20
Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
23
---
19
include/block/block_int.h | 7 +++++++
24
include/block/block-global-state.h | 3 +++
20
block/blkdebug.c | 16 ++++++++++++++++
25
block.c | 21 +++++++++++++++++++++
21
block/blklogwrites.c | 8 ++++++++
26
block/blkdebug.c | 9 +++------
22
block/crypto.c | 8 ++++++++
27
block/blklogwrites.c | 7 ++-----
23
block/curl.c | 21 +++++++++++++++++++++
28
block/blkreplay.c | 7 ++-----
24
block/gluster.c | 19 +++++++++++++++++++
29
block/blkverify.c | 9 +++------
25
block/iscsi.c | 18 ++++++++++++++++++
30
block/bochs.c | 7 +++----
26
block/nbd.c | 14 ++++++++++++++
31
block/cloop.c | 7 +++----
27
block/nfs.c | 11 +++++++++++
32
block/copy-before-write.c | 9 ++++-----
28
block/null.c | 9 +++++++++
33
block/copy-on-read.c | 9 ++++-----
29
block/nvme.c | 8 ++++++++
34
block/crypto.c | 11 ++++++-----
30
block/qcow.c | 7 +++++++
35
block/dmg.c | 7 +++----
31
block/qcow2.c | 7 +++++++
36
block/filter-compress.c | 8 +++-----
32
block/quorum.c | 11 +++++++++++
37
block/parallels.c | 7 +++----
33
block/raw-format.c | 10 +++++++++-
38
block/preallocate.c | 9 ++++-----
34
block/rbd.c | 14 ++++++++++++++
39
block/qcow.c | 6 ++----
35
block/replication.c | 8 ++++++++
40
block/qcow2.c | 8 ++++----
36
block/sheepdog.c | 12 ++++++++++++
41
block/qed.c | 8 ++++----
37
block/ssh.c | 12 ++++++++++++
42
block/replication.c | 8 +++-----
38
block/throttle.c | 7 +++++++
43
block/throttle.c | 8 +++-----
39
block/vpc.c | 7 +++++++
44
block/vdi.c | 7 +++----
40
block/vvfat.c | 12 ++++++++++++
45
block/vhdx.c | 7 +++----
41
block/vxhs.c | 11 +++++++++++
46
block/vmdk.c | 7 +++----
42
23 files changed, 256 insertions(+), 1 deletion(-)
47
block/vpc.c | 7 +++----
48
24 files changed, 95 insertions(+), 101 deletions(-)
43
49
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
50
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
45
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
52
--- a/include/block/block-global-state.h
47
+++ b/include/block/block_int.h
53
+++ b/include/block/block-global-state.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
54
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
49
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
55
const BdrvChildClass *child_class,
50
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
56
BdrvChildRole child_role,
51
QLIST_ENTRY(BlockDriver) list;
57
bool allow_none, Error **errp);
58
+int bdrv_open_file_child(const char *filename,
59
+ QDict *options, const char *bdref_key,
60
+ BlockDriverState *parent, Error **errp);
61
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
62
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
63
Error **errp);
64
diff --git a/block.c b/block.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block.c
67
+++ b/block.c
68
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
69
errp);
70
}
71
72
+/*
73
+ * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
74
+ */
75
+int bdrv_open_file_child(const char *filename,
76
+ QDict *options, const char *bdref_key,
77
+ BlockDriverState *parent, Error **errp)
78
+{
79
+ BdrvChildRole role;
52
+
80
+
53
+ /* Pointer to a NULL-terminated array of names of strong options
81
+ /* commit_top and mirror_top don't use this function */
54
+ * that can be specified for bdrv_open(). A strong option is one
82
+ assert(!parent->drv->filtered_child_is_backing);
55
+ * that changes the data of a BDS.
83
+
56
+ * If this pointer is NULL, the array is considered empty.
84
+ role = parent->drv->is_filter ?
57
+ * "filename" and "driver" are always considered strong. */
85
+ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
58
+ const char *const *strong_runtime_opts;
86
+
59
};
87
+ parent->file = bdrv_open_child(filename, options, bdref_key, parent,
60
88
+ &child_of_bds, role, false, errp);
61
typedef struct BlockLimits {
89
+
90
+ return parent->file ? 0 : -EINVAL;
91
+}
92
+
93
/*
94
* TODO Future callers may need to specify parent/child_class in order for
95
* option inheritance to work. Existing callers use it for the root node.
62
diff --git a/block/blkdebug.c b/block/blkdebug.c
96
diff --git a/block/blkdebug.c b/block/blkdebug.c
63
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
64
--- a/block/blkdebug.c
98
--- a/block/blkdebug.c
65
+++ b/block/blkdebug.c
99
+++ b/block/blkdebug.c
66
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
100
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
67
return 0;
101
}
68
}
102
69
103
/* Open the image file */
70
+static const char *const blkdebug_strong_runtime_opts[] = {
104
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
71
+ "config",
105
- bs, &child_of_bds,
72
+ "inject-error.",
106
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
73
+ "set-state.",
107
- false, errp);
74
+ "align",
108
- if (!bs->file) {
75
+ "max-transfer",
109
- ret = -EINVAL;
76
+ "opt-write-zero",
110
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
77
+ "max-write-zero",
111
+ bs, errp);
78
+ "opt-discard",
112
+ if (ret < 0) {
79
+ "max-discard",
113
goto out;
80
+
114
}
81
+ NULL
115
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
116
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
97
index XXXXXXX..XXXXXXX 100644
117
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blklogwrites.c
118
--- a/block/blklogwrites.c
99
+++ b/block/blklogwrites.c
119
+++ b/block/blklogwrites.c
100
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
120
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
101
LOG_DISCARD_FLAG, false);
121
}
102
}
122
103
123
/* Open the file */
104
+static const char *const blk_log_writes_strong_runtime_opts[] = {
124
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
105
+ "log-append",
125
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
106
+ "log-sector-size",
126
- errp);
107
+
127
- if (!bs->file) {
108
+ NULL
128
- ret = -EINVAL;
109
+};
129
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
110
+
130
+ if (ret < 0) {
111
static BlockDriver bdrv_blk_log_writes = {
131
goto fail;
112
.format_name = "blklogwrites",
132
}
113
.instance_size = sizeof(BDRVBlkLogWritesState),
133
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
134
diff --git a/block/blkreplay.c b/block/blkreplay.c
115
.bdrv_co_block_status = bdrv_co_block_status_from_file,
135
index XXXXXXX..XXXXXXX 100644
116
136
--- a/block/blkreplay.c
117
.is_filter = true,
137
+++ b/block/blkreplay.c
118
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
138
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
119
};
139
int ret;
120
140
121
static void bdrv_blk_log_writes_init(void)
141
/* Open the image file */
142
- bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
143
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
144
- false, errp);
145
- if (!bs->file) {
146
- ret = -EINVAL;
147
+ ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
148
+ if (ret < 0) {
149
goto fail;
150
}
151
152
diff --git a/block/blkverify.c b/block/blkverify.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/blkverify.c
155
+++ b/block/blkverify.c
156
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
157
}
158
159
/* Open the raw file */
160
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
161
- bs, &child_of_bds,
162
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
163
- false, errp);
164
- if (!bs->file) {
165
- ret = -EINVAL;
166
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
167
+ bs, errp);
168
+ if (ret < 0) {
169
goto fail;
170
}
171
172
diff --git a/block/bochs.c b/block/bochs.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/bochs.c
175
+++ b/block/bochs.c
176
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
177
return ret;
178
}
179
180
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
181
- BDRV_CHILD_IMAGE, false, errp);
182
- if (!bs->file) {
183
- return -EINVAL;
184
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
185
+ if (ret < 0) {
186
+ return ret;
187
}
188
189
ret = bdrv_pread(bs->file, 0, sizeof(bochs), &bochs, 0);
190
diff --git a/block/cloop.c b/block/cloop.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/cloop.c
193
+++ b/block/cloop.c
194
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
195
return ret;
196
}
197
198
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
199
- BDRV_CHILD_IMAGE, false, errp);
200
- if (!bs->file) {
201
- return -EINVAL;
202
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
203
+ if (ret < 0) {
204
+ return ret;
205
}
206
207
/* read header */
208
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/copy-before-write.c
211
+++ b/block/copy-before-write.c
212
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
213
int64_t cluster_size;
214
g_autoptr(BlockdevOptions) full_opts = NULL;
215
BlockdevOptionsCbw *opts;
216
+ int ret;
217
218
full_opts = cbw_parse_options(options, errp);
219
if (!full_opts) {
220
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
221
assert(full_opts->driver == BLOCKDEV_DRIVER_COPY_BEFORE_WRITE);
222
opts = &full_opts->u.copy_before_write;
223
224
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
225
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
226
- false, errp);
227
- if (!bs->file) {
228
- return -EINVAL;
229
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
230
+ if (ret < 0) {
231
+ return ret;
232
}
233
234
s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
235
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/block/copy-on-read.c
238
+++ b/block/copy-on-read.c
239
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
240
BDRVStateCOR *state = bs->opaque;
241
/* Find a bottom node name, if any */
242
const char *bottom_node = qdict_get_try_str(options, "bottom");
243
+ int ret;
244
245
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
246
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
247
- false, errp);
248
- if (!bs->file) {
249
- return -EINVAL;
250
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
251
+ if (ret < 0) {
252
+ return ret;
253
}
254
255
bs->supported_read_flags = BDRV_REQ_PREFETCH;
122
diff --git a/block/crypto.c b/block/crypto.c
256
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
257
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
258
--- a/block/crypto.c
125
+++ b/block/crypto.c
259
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
260
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
127
return spec_info;
261
{
128
}
262
BlockCrypto *crypto = bs->opaque;
129
263
QemuOpts *opts = NULL;
130
+static const char *const block_crypto_strong_runtime_opts[] = {
264
- int ret = -EINVAL;
131
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
265
+ int ret;
132
+
266
QCryptoBlockOpenOptions *open_opts = NULL;
133
+ NULL
267
unsigned int cflags = 0;
134
+};
268
QDict *cryptoopts = NULL;
135
+
269
136
BlockDriver bdrv_crypto_luks = {
270
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
137
.format_name = "luks",
271
- BDRV_CHILD_IMAGE, false, errp);
138
.instance_size = sizeof(BlockCrypto),
272
- if (!bs->file) {
139
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
273
- return -EINVAL;
140
.bdrv_getlength = block_crypto_getlength,
274
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
141
.bdrv_get_info = block_crypto_get_info_luks,
275
+ if (ret < 0) {
142
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
276
+ return ret;
143
+
277
}
144
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
278
145
};
279
bs->supported_write_flags = BDRV_REQ_FUA &
146
280
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
147
static void block_crypto_init(void)
281
148
diff --git a/block/curl.c b/block/curl.c
282
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
149
index XXXXXXX..XXXXXXX 100644
283
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
150
--- a/block/curl.c
284
+ ret = -EINVAL;
151
+++ b/block/curl.c
285
goto cleanup;
152
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
286
}
153
return s->len;
287
154
}
288
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
155
289
156
+static const char *const curl_strong_runtime_opts[] = {
290
open_opts = block_crypto_open_opts_init(cryptoopts, errp);
157
+ CURL_BLOCK_OPT_URL,
291
if (!open_opts) {
158
+ CURL_BLOCK_OPT_SSLVERIFY,
292
+ ret = -EINVAL;
159
+ CURL_BLOCK_OPT_COOKIE,
293
goto cleanup;
160
+ CURL_BLOCK_OPT_COOKIE_SECRET,
294
}
161
+ CURL_BLOCK_OPT_USERNAME,
295
162
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
296
diff --git a/block/dmg.c b/block/dmg.c
163
+ CURL_BLOCK_OPT_PROXY_USERNAME,
297
index XXXXXXX..XXXXXXX 100644
164
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
298
--- a/block/dmg.c
165
+
299
+++ b/block/dmg.c
166
+ NULL
300
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
167
+};
301
return ret;
168
+
302
}
169
static BlockDriver bdrv_http = {
303
170
.format_name = "http",
304
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
171
.protocol_name = "http",
305
- BDRV_CHILD_IMAGE, false, errp);
172
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
306
- if (!bs->file) {
173
307
- return -EINVAL;
174
.bdrv_detach_aio_context = curl_detach_aio_context,
308
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
175
.bdrv_attach_aio_context = curl_attach_aio_context,
309
+ if (ret < 0) {
176
+
310
+ return ret;
177
+ .strong_runtime_opts = curl_strong_runtime_opts,
311
}
178
};
312
179
313
block_module_load_one("dmg-bz2");
180
static BlockDriver bdrv_https = {
314
diff --git a/block/filter-compress.c b/block/filter-compress.c
181
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
315
index XXXXXXX..XXXXXXX 100644
182
316
--- a/block/filter-compress.c
183
.bdrv_detach_aio_context = curl_detach_aio_context,
317
+++ b/block/filter-compress.c
184
.bdrv_attach_aio_context = curl_attach_aio_context,
318
@@ -XXX,XX +XXX,XX @@
185
+
319
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
186
+ .strong_runtime_opts = curl_strong_runtime_opts,
320
Error **errp)
187
};
321
{
188
322
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
189
static BlockDriver bdrv_ftp = {
323
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
190
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
324
- false, errp);
191
325
- if (!bs->file) {
192
.bdrv_detach_aio_context = curl_detach_aio_context,
326
- return -EINVAL;
193
.bdrv_attach_aio_context = curl_attach_aio_context,
327
+ int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
194
+
328
+ if (ret < 0) {
195
+ .strong_runtime_opts = curl_strong_runtime_opts,
329
+ return ret;
196
};
330
}
197
331
198
static BlockDriver bdrv_ftps = {
332
if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
333
diff --git a/block/parallels.c b/block/parallels.c
200
334
index XXXXXXX..XXXXXXX 100644
201
.bdrv_detach_aio_context = curl_detach_aio_context,
335
--- a/block/parallels.c
202
.bdrv_attach_aio_context = curl_attach_aio_context,
336
+++ b/block/parallels.c
203
+
337
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
204
+ .strong_runtime_opts = curl_strong_runtime_opts,
338
Error *local_err = NULL;
205
};
339
char *buf;
206
340
207
static void curl_block_init(void)
341
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
208
diff --git a/block/gluster.c b/block/gluster.c
342
- BDRV_CHILD_IMAGE, false, errp);
209
index XXXXXXX..XXXXXXX 100644
343
- if (!bs->file) {
210
--- a/block/gluster.c
344
- return -EINVAL;
211
+++ b/block/gluster.c
345
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
346
+ if (ret < 0) {
213
}
347
+ return ret;
214
348
}
215
349
216
+static const char *const gluster_strong_open_opts[] = {
350
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
217
+ GLUSTER_OPT_VOLUME,
351
diff --git a/block/preallocate.c b/block/preallocate.c
218
+ GLUSTER_OPT_PATH,
352
index XXXXXXX..XXXXXXX 100644
219
+ GLUSTER_OPT_TYPE,
353
--- a/block/preallocate.c
220
+ GLUSTER_OPT_SERVER_PATTERN,
354
+++ b/block/preallocate.c
221
+ GLUSTER_OPT_HOST,
355
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
222
+ GLUSTER_OPT_PORT,
356
Error **errp)
223
+ GLUSTER_OPT_TO,
357
{
224
+ GLUSTER_OPT_IPV4,
358
BDRVPreallocateState *s = bs->opaque;
225
+ GLUSTER_OPT_IPV6,
359
+ int ret;
226
+ GLUSTER_OPT_SOCKET,
360
227
+
361
/*
228
+ NULL
362
* s->data_end and friends should be initialized on permission update.
229
+};
363
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
230
+
364
*/
231
static BlockDriver bdrv_gluster = {
365
s->file_end = s->zero_start = s->data_end = -EINVAL;
232
.format_name = "gluster",
366
233
.protocol_name = "gluster",
367
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
234
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
368
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
235
#endif
369
- false, errp);
236
.bdrv_co_block_status = qemu_gluster_co_block_status,
370
- if (!bs->file) {
237
.create_opts = &qemu_gluster_create_opts,
371
- return -EINVAL;
238
+ .strong_runtime_opts = gluster_strong_open_opts,
372
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
239
};
373
+ if (ret < 0) {
240
374
+ return ret;
241
static BlockDriver bdrv_gluster_tcp = {
375
}
242
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
376
243
#endif
377
if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
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
378
diff --git a/block/qcow.c b/block/qcow.c
445
index XXXXXXX..XXXXXXX 100644
379
index XXXXXXX..XXXXXXX 100644
446
--- a/block/qcow.c
380
--- a/block/qcow.c
447
+++ b/block/qcow.c
381
+++ b/block/qcow.c
448
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
382
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
449
}
383
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
450
};
384
encryptfmt = qdict_get_try_str(encryptopts, "format");
451
385
452
+static const char *const qcow_strong_runtime_opts[] = {
386
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
453
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
387
- BDRV_CHILD_IMAGE, false, errp);
454
+
388
- if (!bs->file) {
455
+ NULL
389
- ret = -EINVAL;
456
+};
390
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
457
+
391
+ if (ret < 0) {
458
static BlockDriver bdrv_qcow = {
392
goto fail;
459
.format_name    = "qcow",
393
}
460
.instance_size    = sizeof(BDRVQcowState),
394
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
395
diff --git a/block/qcow2.c b/block/qcow2.c
470
index XXXXXXX..XXXXXXX 100644
396
index XXXXXXX..XXXXXXX 100644
471
--- a/block/qcow2.c
397
--- a/block/qcow2.c
472
+++ b/block/qcow2.c
398
+++ b/block/qcow2.c
473
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
399
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
474
}
400
.errp = errp,
475
};
401
.ret = -EINPROGRESS
476
402
};
477
+static const char *const qcow2_strong_runtime_opts[] = {
403
+ int ret;
478
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
404
479
+
405
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
480
+ NULL
406
- BDRV_CHILD_IMAGE, false, errp);
481
+};
407
- if (!bs->file) {
482
+
408
- return -EINVAL;
483
BlockDriver bdrv_qcow2 = {
409
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
484
.format_name = "qcow2",
410
+ if (ret < 0) {
485
.instance_size = sizeof(BDRVQcow2State),
411
+ return ret;
486
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
412
}
487
.bdrv_inactivate = qcow2_inactivate,
413
488
414
/* Initialise locks */
489
.create_opts = &qcow2_create_opts,
415
diff --git a/block/qed.c b/block/qed.c
490
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
416
index XXXXXXX..XXXXXXX 100644
491
.bdrv_co_check = qcow2_co_check,
417
--- a/block/qed.c
492
.bdrv_amend_options = qcow2_amend_options,
418
+++ b/block/qed.c
493
419
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
494
diff --git a/block/quorum.c b/block/quorum.c
420
.errp = errp,
495
index XXXXXXX..XXXXXXX 100644
421
.ret = -EINPROGRESS
496
--- a/block/quorum.c
422
};
497
+++ b/block/quorum.c
423
+ int ret;
498
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
424
499
return NULL;
425
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
500
}
426
- BDRV_CHILD_IMAGE, false, errp);
501
427
- if (!bs->file) {
502
+static const char *const quorum_strong_runtime_opts[] = {
428
- return -EINVAL;
503
+ QUORUM_OPT_VOTE_THRESHOLD,
429
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
504
+ QUORUM_OPT_BLKVERIFY,
430
+ if (ret < 0) {
505
+ QUORUM_OPT_REWRITE,
431
+ return ret;
506
+ QUORUM_OPT_READ_PATTERN,
432
}
507
+
433
508
+ NULL
434
bdrv_qed_init_state(bs);
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
524
index XXXXXXX..XXXXXXX 100644
525
--- a/block/raw-format.c
526
+++ b/block/raw-format.c
527
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
528
read_flags, write_flags);
529
}
530
531
+static const char *const raw_strong_runtime_opts[] = {
532
+ "offset",
533
+ "size",
534
+
535
+ NULL
536
+};
537
+
538
BlockDriver bdrv_raw = {
539
.format_name = "raw",
540
.instance_size = sizeof(BDRVRawState),
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
435
diff --git a/block/replication.c b/block/replication.c
584
index XXXXXXX..XXXXXXX 100644
436
index XXXXXXX..XXXXXXX 100644
585
--- a/block/replication.c
437
--- a/block/replication.c
586
+++ b/block/replication.c
438
+++ b/block/replication.c
587
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
439
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
588
aio_context_release(aio_context);
440
const char *mode;
589
}
441
const char *top_id;
590
442
591
+static const char *const replication_strong_runtime_opts[] = {
443
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
592
+ REPLICATION_MODE,
444
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
593
+ REPLICATION_TOP_ID,
445
- false, errp);
594
+
446
- if (!bs->file) {
595
+ NULL
447
- return -EINVAL;
596
+};
448
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
597
+
449
+ if (ret < 0) {
598
BlockDriver bdrv_replication = {
450
+ return ret;
599
.format_name = "replication",
451
}
600
.instance_size = sizeof(BDRVReplicationState),
452
601
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_replication = {
453
ret = -EINVAL;
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
454
diff --git a/block/throttle.c b/block/throttle.c
684
index XXXXXXX..XXXXXXX 100644
455
index XXXXXXX..XXXXXXX 100644
685
--- a/block/throttle.c
456
--- a/block/throttle.c
686
+++ b/block/throttle.c
457
+++ b/block/throttle.c
687
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs)
458
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
688
atomic_dec(&tgm->io_limits_disabled);
459
char *group;
689
}
460
int ret;
690
461
691
+static const char *const throttle_strong_runtime_opts[] = {
462
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
692
+ QEMU_OPT_THROTTLE_GROUP_NAME,
463
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
693
+
464
- false, errp);
694
+ NULL
465
- if (!bs->file) {
695
+};
466
- return -EINVAL;
696
+
467
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
697
static BlockDriver bdrv_throttle = {
468
+ if (ret < 0) {
698
.format_name = "throttle",
469
+ return ret;
699
.instance_size = sizeof(ThrottleGroupMember),
470
}
700
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
471
bs->supported_write_flags = bs->file->bs->supported_write_flags |
701
.bdrv_co_drain_end = throttle_co_drain_end,
472
BDRV_REQ_WRITE_UNCHANGED;
702
473
diff --git a/block/vdi.c b/block/vdi.c
703
.is_filter = true,
474
index XXXXXXX..XXXXXXX 100644
704
+ .strong_runtime_opts = throttle_strong_runtime_opts,
475
--- a/block/vdi.c
705
};
476
+++ b/block/vdi.c
706
477
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
707
static void bdrv_throttle_init(void)
478
int ret;
479
QemuUUID uuid_link, uuid_parent;
480
481
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
482
- BDRV_CHILD_IMAGE, false, errp);
483
- if (!bs->file) {
484
- return -EINVAL;
485
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
486
+ if (ret < 0) {
487
+ return ret;
488
}
489
490
logout("\n");
491
diff --git a/block/vhdx.c b/block/vhdx.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/block/vhdx.c
494
+++ b/block/vhdx.c
495
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
496
uint64_t signature;
497
Error *local_err = NULL;
498
499
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
500
- BDRV_CHILD_IMAGE, false, errp);
501
- if (!bs->file) {
502
- return -EINVAL;
503
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
504
+ if (ret < 0) {
505
+ return ret;
506
}
507
508
s->bat = NULL;
509
diff --git a/block/vmdk.c b/block/vmdk.c
510
index XXXXXXX..XXXXXXX 100644
511
--- a/block/vmdk.c
512
+++ b/block/vmdk.c
513
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
514
BDRVVmdkState *s = bs->opaque;
515
uint32_t magic;
516
517
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
518
- BDRV_CHILD_IMAGE, false, errp);
519
- if (!bs->file) {
520
- return -EINVAL;
521
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
522
+ if (ret < 0) {
523
+ return ret;
524
}
525
526
buf = vmdk_read_desc(bs->file, 0, errp);
708
diff --git a/block/vpc.c b/block/vpc.c
527
diff --git a/block/vpc.c b/block/vpc.c
709
index XXXXXXX..XXXXXXX 100644
528
index XXXXXXX..XXXXXXX 100644
710
--- a/block/vpc.c
529
--- a/block/vpc.c
711
+++ b/block/vpc.c
530
+++ b/block/vpc.c
712
@@ -XXX,XX +XXX,XX @@ static QemuOptsList vpc_create_opts = {
531
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
713
}
532
int ret;
714
};
533
int64_t bs_size;
715
534
716
+static const char *const vpc_strong_runtime_opts[] = {
535
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
717
+ VPC_OPT_SIZE_CALC,
536
- BDRV_CHILD_IMAGE, false, errp);
718
+
537
- if (!bs->file) {
719
+ NULL
538
- return -EINVAL;
720
+};
539
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
721
+
540
+ if (ret < 0) {
722
static BlockDriver bdrv_vpc = {
541
+ return ret;
723
.format_name = "vpc",
542
}
724
.instance_size = sizeof(BDRVVPCState),
543
725
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
544
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
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
--
545
--
793
2.20.1
546
2.37.3
794
795
diff view generated by jsdifflib
1
virtio_blk_dma_restart_bh() submits new requests, so in order to make
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
sure that these requests are not started inside a drained section of the
3
attached BlockBackend, we need to make sure that draining the
4
BlockBackend waits for the BH to be executed.
5
2
6
This BH is still questionable because its scheduled in the main thread
3
We don't need to remove bs->file, generic layer takes care of it. No
7
instead of the configured iothread. Leave a FIXME comment for this.
4
other driver cares to remove bs->file on failure by hand.
8
5
9
But with this fix, enabling the data plane at least waits for these
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
requests (in bdrv_set_aio_context()) instead of changing the AioContext
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
under their feet and making them run in the wrong thread, causing
8
Message-Id: <20220726201134.924743-4-vsementsov@yandex-team.ru>
12
crashes and failures (e.g. due to missing locking).
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
11
---
16
hw/block/virtio-blk.c | 4 ++++
12
block/blklogwrites.c | 4 ----
17
1 file changed, 4 insertions(+)
13
1 file changed, 4 deletions(-)
18
14
19
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
15
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/block/virtio-blk.c
17
--- a/block/blklogwrites.c
22
+++ b/hw/block/virtio-blk.c
18
+++ b/block/blklogwrites.c
23
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
19
@@ -XXX,XX +XXX,XX @@ fail_log:
24
if (mrb.num_reqs) {
20
s->log_file = NULL;
25
virtio_blk_submit_multireq(s->blk, &mrb);
26
}
21
}
27
+ blk_dec_in_flight(s->conf.conf.blk);
22
fail:
28
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
23
- if (ret < 0) {
29
}
24
- bdrv_unref_child(bs, bs->file);
30
25
- bs->file = NULL;
31
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
26
- }
32
}
27
qemu_opts_del(opts);
33
28
return ret;
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
}
29
}
43
--
30
--
44
2.20.1
31
2.37.3
45
46
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
blkverify's BDSs have a file BDS, but we do not want this to be
3
test_parallel_perm_update() does two things that we are going to
4
preferred over the raw node. There is no way to decide between the two
4
restrict in the near future:
5
(and not really a reason to, either), so just return NULL in blkverify's
6
implementation of bdrv_dirname().
7
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
1. It updates bs->file field by hand. bs->file will be managed
9
Reviewed-by: Eric Blake <eblake@redhat.com>
7
automatically by generic code (together with bs->children list).
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
11
Message-id: 20190201192935.18394-16-mreitz@redhat.com
9
Let's better refactor our "tricky" bds to have own state where one
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
of children is linked as "selected".
11
This also looks less "tricky", so avoid using this word.
12
13
2. It create FILTERED children that are not PRIMARY. Except for tests
14
all FILTERED children in the Qemu block layer are always PRIMARY as
15
well. We are going to formalize this rule, so let's better use DATA
16
children here.
17
18
3. It creates more than one FILTERED child, which is already abandoned
19
in BDRV_CHILD_FILTERED's description.
20
21
While being here, update the picture to better correspond to the test
22
code.
23
24
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
25
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
26
Message-Id: <20220726201134.924743-5-vsementsov@yandex-team.ru>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
28
---
14
block/blkverify.c | 10 ++++++++++
29
tests/unit/test-bdrv-graph-mod.c | 80 +++++++++++++++++++-------------
15
1 file changed, 10 insertions(+)
30
1 file changed, 49 insertions(+), 31 deletions(-)
16
31
17
diff --git a/block/blkverify.c b/block/blkverify.c
32
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
18
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
34
--- a/tests/unit/test-bdrv-graph-mod.c
20
+++ b/block/blkverify.c
35
+++ b/tests/unit/test-bdrv-graph-mod.c
21
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
36
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
37
bdrv_unref(top);
38
}
39
40
-static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
41
- BdrvChildRole role,
42
- BlockReopenQueue *reopen_queue,
43
- uint64_t perm, uint64_t shared,
44
- uint64_t *nperm, uint64_t *nshared)
45
+/*
46
+ * write-to-selected node may have several DATA children, one of them may be
47
+ * "selected". Exclusive write permission is taken on selected child.
48
+ *
49
+ * We don't realize write handler itself, as we need only to test how permission
50
+ * update works.
51
+ */
52
+typedef struct BDRVWriteToSelectedState {
53
+ BdrvChild *selected;
54
+} BDRVWriteToSelectedState;
55
+
56
+static void write_to_selected_perms(BlockDriverState *bs, BdrvChild *c,
57
+ BdrvChildRole role,
58
+ BlockReopenQueue *reopen_queue,
59
+ uint64_t perm, uint64_t shared,
60
+ uint64_t *nperm, uint64_t *nshared)
61
{
62
- if (bs->file && c == bs->file) {
63
+ BDRVWriteToSelectedState *s = bs->opaque;
64
+
65
+ if (s->selected && c == s->selected) {
66
*nperm = BLK_PERM_WRITE;
67
*nshared = BLK_PERM_ALL & ~BLK_PERM_WRITE;
68
} else {
69
@@ -XXX,XX +XXX,XX @@ static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
22
}
70
}
23
}
71
}
24
72
25
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
73
-static BlockDriver bdrv_write_to_file = {
26
+{
74
- .format_name = "tricky-perm",
27
+ /* In general, there are two BDSs with different dirnames below this one;
75
- .bdrv_child_perm = write_to_file_perms,
28
+ * so there is no unique dirname we could return (unless both are equal by
76
+static BlockDriver bdrv_write_to_selected = {
29
+ * chance). Therefore, to be consistent, just always return NULL. */
77
+ .format_name = "write-to-selected",
30
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
78
+ .instance_size = sizeof(BDRVWriteToSelectedState),
31
+ return NULL;
79
+ .bdrv_child_perm = write_to_selected_perms,
32
+}
80
};
33
+
81
34
static BlockDriver bdrv_blkverify = {
82
35
.format_name = "blkverify",
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
36
.protocol_name = "blkverify",
84
* The following test shows that topological-sort order is required for
37
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
85
* permission update, simple DFS is not enough.
38
.bdrv_child_perm = bdrv_filter_default_perms,
86
*
39
.bdrv_getlength = blkverify_getlength,
87
- * Consider the block driver which has two filter children: one active
40
.bdrv_refresh_filename = blkverify_refresh_filename,
88
- * with exclusive write access and one inactive with no specific
41
+ .bdrv_dirname = blkverify_dirname,
89
- * permissions.
42
90
+ * Consider the block driver (write-to-selected) which has two children: one is
43
.bdrv_co_preadv = blkverify_co_preadv,
91
+ * selected so we have exclusive write access to it and for the other one we
44
.bdrv_co_pwritev = blkverify_co_pwritev,
92
+ * don't need any specific permissions.
93
*
94
* And, these two children has a common base child, like this:
95
+ * (additional "top" on top is used in test just because the only public
96
+ * function to update permission should get a specific child to update.
97
+ * Making bdrv_refresh_perms() public just for this test isn't worth it)
98
*
99
- * ┌─────┐ ┌──────┐
100
- * │ fl2 │ ◀── │ top │
101
- * └─────┘ └──────┘
102
+ * ┌─────┐ ┌───────────────────┐ ┌─────┐
103
+ * │ fl2 │ ◀── │ write-to-selected │ ◀── │ top │
104
+ * └─────┘ └───────────────────┘ └─────┘
105
* │ │
106
* │ │ w
107
* │ ▼
108
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
109
*
110
* So, exclusive write is propagated.
111
*
112
- * Assume, we want to make fl2 active instead of fl1.
113
- * So, we set some option for top driver and do permission update.
114
+ * Assume, we want to select fl2 instead of fl1.
115
+ * So, we set some option for write-to-selected driver and do permission update.
116
*
117
* With simple DFS, if permission update goes first through
118
- * top->fl1->base branch it will succeed: it firstly drop exclusive write
119
- * permissions and than apply them for another BdrvChildren.
120
- * But if permission update goes first through top->fl2->base branch it
121
- * will fail, as when we try to update fl2->base child, old not yet
122
+ * write-to-selected -> fl1 -> base branch it will succeed: it firstly drop
123
+ * exclusive write permissions and than apply them for another BdrvChildren.
124
+ * But if permission update goes first through write-to-selected -> fl2 -> base
125
+ * branch it will fail, as when we try to update fl2->base child, old not yet
126
* updated fl1->base child will be in conflict.
127
*
128
* With topological-sort order we always update parents before children, so fl1
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
130
static void test_parallel_perm_update(void)
131
{
132
BlockDriverState *top = no_perm_node("top");
133
- BlockDriverState *tricky =
134
- bdrv_new_open_driver(&bdrv_write_to_file, "tricky", BDRV_O_RDWR,
135
+ BlockDriverState *ws =
136
+ bdrv_new_open_driver(&bdrv_write_to_selected, "ws", BDRV_O_RDWR,
137
&error_abort);
138
+ BDRVWriteToSelectedState *s = ws->opaque;
139
BlockDriverState *base = no_perm_node("base");
140
BlockDriverState *fl1 = pass_through_node("fl1");
141
BlockDriverState *fl2 = pass_through_node("fl2");
142
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
143
*/
144
bdrv_ref(base);
145
146
- bdrv_attach_child(top, tricky, "file", &child_of_bds, BDRV_CHILD_DATA,
147
+ bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA,
148
&error_abort);
149
- c_fl1 = bdrv_attach_child(tricky, fl1, "first", &child_of_bds,
150
- BDRV_CHILD_FILTERED, &error_abort);
151
- c_fl2 = bdrv_attach_child(tricky, fl2, "second", &child_of_bds,
152
- BDRV_CHILD_FILTERED, &error_abort);
153
+ c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds,
154
+ BDRV_CHILD_DATA, &error_abort);
155
+ c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
156
+ BDRV_CHILD_DATA, &error_abort);
157
bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
158
&error_abort);
159
bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
160
&error_abort);
161
162
/* Select fl1 as first child to be active */
163
- tricky->file = c_fl1;
164
+ s->selected = c_fl1;
165
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
166
167
assert(c_fl1->perm & BLK_PERM_WRITE);
168
assert(!(c_fl2->perm & BLK_PERM_WRITE));
169
170
/* Now, try to switch active child and update permissions */
171
- tricky->file = c_fl2;
172
+ s->selected = c_fl2;
173
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
174
175
assert(c_fl2->perm & BLK_PERM_WRITE);
176
assert(!(c_fl1->perm & BLK_PERM_WRITE));
177
178
/* Switch once more, to not care about real child order in the list */
179
- tricky->file = c_fl1;
180
+ s->selected = c_fl1;
181
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
182
183
assert(c_fl1->perm & BLK_PERM_WRITE);
45
--
184
--
46
2.20.1
185
2.37.3
47
186
48
187
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
8908b253c4ad5f8874c8d13abec169c696a5cd32 has implemented filtering of
3
We do add COW child to the node. In future we are going to forbid
4
remote paths for NFS, but forgot SSH. This patch takes care of that.
4
adding COW child to the node that doesn't support backing. So, fix it
5
here now.
5
6
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Don't worry about setting bs->backing itself: in further commit we'll
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
update the block-layer to automatically set/unset this field in generic
8
Message-id: 20190210145736.1486-9-mreitz@redhat.com
9
code.
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Message-Id: <20220726201134.924743-6-vsementsov@yandex-team.ru>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
16
---
11
tests/qemu-iotests/common.rc | 1 +
17
tests/unit/test-bdrv-drain.c | 1 +
12
1 file changed, 1 insertion(+)
18
1 file changed, 1 insertion(+)
13
19
14
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
20
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/common.rc
22
--- a/tests/unit/test-bdrv-drain.c
17
+++ b/tests/qemu-iotests/common.rc
23
+++ b/tests/unit/test-bdrv-drain.c
18
@@ -XXX,XX +XXX,XX @@ else
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_co_drain_end(BlockDriverState *bs)
19
TEST_IMG="nbd:127.0.0.1:10810"
25
static BlockDriver bdrv_replace_test = {
20
elif [ "$IMGPROTO" = "ssh" ]; then
26
.format_name = "replace_test",
21
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
27
.instance_size = sizeof(BDRVReplaceTestState),
22
+ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
28
+ .supports_backing = true,
23
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
29
24
elif [ "$IMGPROTO" = "nfs" ]; then
30
.bdrv_close = bdrv_replace_test_close,
25
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
31
.bdrv_co_preadv = bdrv_replace_test_co_preadv,
26
--
32
--
27
2.20.1
33
2.37.3
28
29
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
bdrv_pass_through is used as filter, even all node variables has
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
4
corresponding names. We want to append it, so it should be
5
Message-id: 20190201192935.18394-29-mreitz@redhat.com
5
backing-child-based filter like mirror_top.
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
So, in test_update_perm_tree, first child should be DATA, as we don't
7
want filters with two filtered children.
8
9
bdrv_exclusive_writer is used as a filter once. So it should be filter
10
anyway. We want to append it, so it should be backing-child-based
11
fitler too.
12
13
Make all FILTERED children to be PRIMARY as well. We are going to force
14
this rule by assertion soon.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
17
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
18
Message-Id: <20220726201134.924743-7-vsementsov@yandex-team.ru>
19
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
21
---
8
block/curl.c | 21 +++++++++++++++++++++
22
include/block/block_int-common.h | 5 +++--
9
1 file changed, 21 insertions(+)
23
tests/unit/test-bdrv-graph-mod.c | 24 +++++++++++++++++-------
24
2 files changed, 20 insertions(+), 9 deletions(-)
10
25
11
diff --git a/block/curl.c b/block/curl.c
26
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
12
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
13
--- a/block/curl.c
28
--- a/include/block/block_int-common.h
14
+++ b/block/curl.c
29
+++ b/include/block/block_int-common.h
15
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
16
return s->len;
31
/*
17
}
32
* Only make sense for filter drivers, for others must be false.
18
33
* If true, filtered child is bs->backing. Otherwise it's bs->file.
19
+static void curl_refresh_filename(BlockDriverState *bs)
34
- * Only two internal filters use bs->backing as filtered child and has this
20
+{
35
- * field set to true: mirror_top and commit_top.
21
+ BDRVCURLState *s = bs->opaque;
36
+ * Two internal filters use bs->backing as filtered child and has this
22
+
37
+ * field set to true: mirror_top and commit_top. There also two such test
23
+ /* "readahead" and "timeout" do not change the guest-visible data,
38
+ * filters in tests/unit/test-bdrv-graph-mod.c.
24
+ * so ignore them */
39
*
25
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
40
* Never create any more such filters!
26
+ s->cookie || s->username || s->password || s->proxyusername ||
41
*
27
+ s->proxypassword)
42
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
28
+ {
43
index XXXXXXX..XXXXXXX 100644
29
+ return;
44
--- a/tests/unit/test-bdrv-graph-mod.c
30
+ }
45
+++ b/tests/unit/test-bdrv-graph-mod.c
31
+
46
@@ -XXX,XX +XXX,XX @@
32
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
47
33
+}
48
static BlockDriver bdrv_pass_through = {
34
+
49
.format_name = "pass-through",
35
+
50
+ .is_filter = true,
36
static const char *const curl_strong_runtime_opts[] = {
51
+ .filtered_child_is_backing = true,
37
CURL_BLOCK_OPT_URL,
52
.bdrv_child_perm = bdrv_default_perms,
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
};
53
};
46
54
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
55
@@ -XXX,XX +XXX,XX @@ static void exclusive_write_perms(BlockDriverState *bs, BdrvChild *c,
48
.bdrv_detach_aio_context = curl_detach_aio_context,
56
49
.bdrv_attach_aio_context = curl_attach_aio_context,
57
static BlockDriver bdrv_exclusive_writer = {
50
58
.format_name = "exclusive-writer",
51
+ .bdrv_refresh_filename = curl_refresh_filename,
59
+ .is_filter = true,
52
.strong_runtime_opts = curl_strong_runtime_opts,
60
+ .filtered_child_is_backing = true,
61
.bdrv_child_perm = exclusive_write_perms,
53
};
62
};
54
63
55
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
64
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
56
.bdrv_detach_aio_context = curl_detach_aio_context,
65
blk_insert_bs(root, bs, &error_abort);
57
.bdrv_attach_aio_context = curl_attach_aio_context,
66
58
67
bdrv_attach_child(filter, bs, "child", &child_of_bds,
59
+ .bdrv_refresh_filename = curl_refresh_filename,
68
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
60
.strong_runtime_opts = curl_strong_runtime_opts,
69
+ BDRV_CHILD_DATA, &error_abort);
61
};
70
62
71
ret = bdrv_append(filter, bs, NULL);
63
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
72
g_assert_cmpint(ret, <, 0);
64
.bdrv_detach_aio_context = curl_detach_aio_context,
73
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
65
.bdrv_attach_aio_context = curl_attach_aio_context,
74
*/
66
75
bdrv_ref(base);
67
+ .bdrv_refresh_filename = curl_refresh_filename,
76
68
.strong_runtime_opts = curl_strong_runtime_opts,
77
- bdrv_attach_child(top, fl1, "backing", &child_of_bds, BDRV_CHILD_DATA,
69
};
78
+ bdrv_attach_child(top, fl1, "backing", &child_of_bds,
70
79
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
80
&error_abort);
81
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
82
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
83
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
84
&error_abort);
85
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
86
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
87
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
88
&error_abort);
89
90
bdrv_replace_node(fl1, fl2, &error_abort);
91
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
92
BDRV_CHILD_DATA, &error_abort);
93
c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
94
BDRV_CHILD_DATA, &error_abort);
95
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
96
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
97
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
98
&error_abort);
99
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
100
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
101
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
102
&error_abort);
103
104
/* Select fl1 as first child to be active */
105
@@ -XXX,XX +XXX,XX @@ static void test_append_greedy_filter(void)
106
BlockDriverState *base = no_perm_node("base");
107
BlockDriverState *fl = exclusive_writer_node("fl1");
108
109
- bdrv_attach_child(top, base, "backing", &child_of_bds, BDRV_CHILD_COW,
110
+ bdrv_attach_child(top, base, "backing", &child_of_bds,
111
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
112
&error_abort);
113
114
bdrv_append(fl, base, &error_abort);
71
--
115
--
72
2.20.1
116
2.37.3
73
74
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Add two tests of node graph modification.
3
Make the informal rules formal. In further commit we'll add
4
corresponding assertions.
4
5
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220726201134.924743-8-vsementsov@yandex-team.ru>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
11
---
8
tests/test-bdrv-graph-mod.c | 198 ++++++++++++++++++++++++++++++++++++
12
include/block/block-common.h | 39 ++++++++++++++++++++++++++++++++++++
9
tests/Makefile.include | 2 +
13
1 file changed, 39 insertions(+)
10
2 files changed, 200 insertions(+)
11
create mode 100644 tests/test-bdrv-graph-mod.c
12
14
13
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
15
diff --git a/include/block/block-common.h b/include/block/block-common.h
14
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX
17
--- a/include/block/block-common.h
16
--- /dev/null
18
+++ b/include/block/block-common.h
17
+++ b/tests/test-bdrv-graph-mod.c
19
@@ -XXX,XX +XXX,XX @@ enum {
18
@@ -XXX,XX +XXX,XX @@
20
*
19
+/*
21
* At least one of DATA, METADATA, FILTERED, or COW must be set for
20
+ * Block node graph modifications tests
22
* every child.
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
+ *
23
+ *
96
+ *
24
+ *
97
+ * and then, tries to append filter under node. Expected behavior: fail.
25
+ * = Connection with bs->children, bs->file and bs->backing fields =
98
+ * Otherwise we'll get the following picture, with two BdrvChild'ren, having
99
+ * write permission to one node, without actually sharing it.
100
+ *
26
+ *
101
+ * +--------+
27
+ * 1. Filters
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
+ *
28
+ *
143
+ * Test that bdrv_replace_node, and concretely should_update_child
29
+ * Filter drivers have drv->is_filter = true.
144
+ * do the right thing, i.e. not creating loops on the graph.
145
+ *
30
+ *
146
+ * The test does the following:
31
+ * Filter node has exactly one FILTERED|PRIMARY child, and may have other
147
+ * 1. initial graph:
32
+ * children which must not have these bits (one example is the
33
+ * copy-before-write filter, which also has its target DATA child).
148
+ *
34
+ *
149
+ * +------+ +--------+
35
+ * Filter nodes never have COW children.
150
+ * | root | | filter |
151
+ * +------+ +--------+
152
+ * | |
153
+ * root| target|
154
+ * v v
155
+ * +------+ +--------+
156
+ * | node |<---------| target |
157
+ * +------+ backing +--------+
158
+ *
36
+ *
159
+ * 2. Append @filter above @node. If should_update_child works correctly,
37
+ * For most filters, the filtered child is linked in bs->file, bs->backing is
160
+ * it understands, that backing child of @target should not be updated,
38
+ * NULL. For some filters (as an exception), it is the other way around; those
161
+ * as it will create a loop on node graph. Resulting picture should
39
+ * drivers will have drv->filtered_child_is_backing set to true (see that
162
+ * be the left one, not the right:
40
+ * field’s documentation for what drivers this concerns)
163
+ *
41
+ *
164
+ * +------+ +------+
42
+ * 2. "raw" driver (block/raw-format.c)
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
+ *
43
+ *
181
+ * (good picture) (bad picture)
44
+ * Formally it's not a filter (drv->is_filter = false)
182
+ *
45
+ *
183
+ */
46
+ * bs->backing is always NULL
184
+static void test_should_update_child(void)
47
+ *
185
+{
48
+ * Only has one child, linked in bs->file. Its role is either FILTERED|PRIMARY
186
+ BlockBackend *root = blk_new(0, BLK_PERM_ALL);
49
+ * (like filter) or DATA|PRIMARY depending on options.
187
+ BlockDriverState *bs = no_perm_node("node");
50
+ *
188
+ BlockDriverState *filter = no_perm_node("filter");
51
+ * 3. Other drivers
189
+ BlockDriverState *target = no_perm_node("target");
52
+ *
190
+
53
+ * Don't have any FILTERED children.
191
+ blk_insert_bs(root, bs, &error_abort);
54
+ *
192
+
55
+ * May have at most one COW child. In this case it's linked in bs->backing.
193
+ bdrv_set_backing_hd(target, bs, &error_abort);
56
+ * Otherwise bs->backing is NULL. COW child is never PRIMARY.
194
+
57
+ *
195
+ g_assert(target->backing->bs == bs);
58
+ * May have at most one PRIMARY child. In this case it's linked in bs->file.
196
+ bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
59
+ * Otherwise bs->file is NULL.
197
+ bdrv_append(filter, bs, &error_abort);
60
+ *
198
+ g_assert(target->backing->bs == bs);
61
+ * May also have some other children that don't have the PRIMARY or COW bit set.
199
+
62
*/
200
+ bdrv_unref(bs);
63
enum BdrvChildRoleBits {
201
+ blk_unref(root);
64
/*
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
--
65
--
238
2.20.1
66
2.37.3
239
67
240
68
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
After the previous patch, the only instance of this function left
3
Actually what we chose is a primary child. Let's stress it in the code.
4
is inside qemu-img.c.
5
4
6
qemu-img is using it inside the 'img_snapshot' function to delete
5
We are going to drop indirect pointer logic here in future. Actually
7
snapshots in the SNAPSHOT_DELETE case, based on a "snapshot_name"
6
this commit simplifies the future work: we drop use of indirection in
8
string that refers to the tag, not ID, of the QEMUSnapshotInfo struct.
7
the assertion now.
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
8
14
pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
15
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Based on that, it is unlikely that "snapshot_name" might contain
11
Message-Id: <20220726201134.924743-9-vsementsov@yandex-team.ru>
17
an "id" in SNAPSHOT_DELETE.
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
14
---
28
include/block/snapshot.h | 3 ---
15
block/snapshot.c | 30 ++++++++++--------------------
29
block/snapshot.c | 20 --------------------
16
1 file changed, 10 insertions(+), 20 deletions(-)
30
qemu-img.c | 15 +++++++++++----
31
3 files changed, 11 insertions(+), 27 deletions(-)
32
17
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
18
diff --git a/block/snapshot.c b/block/snapshot.c
48
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
49
--- a/block/snapshot.c
20
--- a/block/snapshot.c
50
+++ b/block/snapshot.c
21
+++ b/block/snapshot.c
51
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
52
return ret;
23
static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
53
}
24
{
54
25
BdrvChild **fallback;
55
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
26
- BdrvChild *child;
56
- const char *id_or_name,
27
+ BdrvChild *child = bdrv_primary_child(bs);
57
- Error **errp)
28
58
-{
29
- /*
59
- int ret;
30
- * The only BdrvChild pointers that are safe to modify (and which
60
- Error *local_err = NULL;
31
- * we can thus return a reference to) are bs->file and
61
-
32
- * bs->backing.
62
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
33
- */
63
- if (ret == -ENOENT || ret == -EINVAL) {
34
- fallback = &bs->file;
64
- error_free(local_err);
35
- if (!*fallback && bs->drv && bs->drv->is_filter) {
65
- local_err = NULL;
36
- fallback = &bs->backing;
66
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
67
- }
37
- }
68
-
38
-
69
- if (ret < 0) {
39
- if (!*fallback) {
70
- error_propagate(errp, local_err);
40
+ /* We allow fallback only to primary child */
71
- }
41
+ if (!child) {
72
- return ret;
42
return NULL;
73
-}
43
}
74
-
44
+ fallback = (child == bs->file ? &bs->file : &bs->backing);
75
int bdrv_snapshot_list(BlockDriverState *bs,
45
+ assert(*fallback == child);
76
QEMUSnapshotInfo **psn_info)
46
77
{
47
/*
78
diff --git a/qemu-img.c b/qemu-img.c
48
* Check that there are no other children that would need to be
79
index XXXXXXX..XXXXXXX 100644
49
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
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
}
50
}
103
break;
51
52
/*
53
- * fallback_ptr is &bs->file or &bs->backing. *fallback_ptr
54
- * was closed above and set to NULL, but the .bdrv_open() call
55
- * has opened it again, because we set the respective option
56
- * (with the qdict_put_str() call above).
57
- * Assert that .bdrv_open() has attached some child on
58
- * *fallback_ptr, and that it has attached the one we wanted
59
- * it to (i.e., fallback_bs).
60
+ * fallback was a primary child. It was closed above and set to NULL,
61
+ * but the .bdrv_open() call has opened it again, because we set the
62
+ * respective option (with the qdict_put_str() call above).
63
+ * Assert that .bdrv_open() has attached the right BDS as primary child.
64
*/
65
- assert(*fallback_ptr && fallback_bs == (*fallback_ptr)->bs);
66
+ assert(bdrv_primary_bs(bs) == fallback_bs);
67
bdrv_unref(fallback_bs);
68
return ret;
104
}
69
}
105
--
70
--
106
2.20.1
71
2.37.3
107
108
diff view generated by jsdifflib
1
The explicit aio_poll() call in bdrv_set_aio_context() was added in
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
commit c2b6428d388 as a workaround for bdrv_drain() failing to achieve
2
3
to actually quiesce everything (specifically the NBD client code to
3
We are going to reimplement this behavior (clear bs->file / bs->backing
4
switch AioContext).
4
pointers automatically when child->bs is cleared) in a nicer way, see
5
5
further commit
6
Now that the NBD client has been fixed to complete this operation during
6
"block: Manipulate bs->file / bs->backing pointers in .attach/.detach".
7
bdrv_drain(), we don't need the workaround any more.
7
8
8
With this revert we bring back a problem that was fixed by b0a9f6fed3d8.
9
It was wrong anyway: aio_poll() must always be run in the home thread of
9
Still the problem was mostly theoretical, we don't have concrete bugs
10
the AioContext.
10
fixed by b0a9f6fed3d8, we don't have a specific test. Probably some
11
11
accidental failures of iotests are related.
12
13
Alternatively, we may merge this and following three reverts into final
14
"block: Manipulate ..." to avoid any kind of regression. But seems that
15
in this case having separate clear revert commits is better.
16
17
This reverts commit b0a9f6fed3d80de610dcd04a7e66f9f30a04174f.
18
19
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
20
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
Message-Id: <20220726201134.924743-10-vsementsov@yandex-team.ru>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
23
---
15
block.c | 4 ----
24
block.c | 102 +++++++++++++-------------------------------------------
16
1 file changed, 4 deletions(-)
25
1 file changed, 23 insertions(+), 79 deletions(-)
17
26
18
diff --git a/block.c b/block.c
27
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
29
--- a/block.c
21
+++ b/block.c
30
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
31
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
23
bdrv_parent_drained_begin(bs, NULL, false);
32
static bool bdrv_recurse_has_child(BlockDriverState *bs,
24
bdrv_drain(bs); /* ensure there are no in-flight requests */
33
BlockDriverState *child);
25
34
26
- while (aio_poll(ctx, false)) {
35
-static void bdrv_child_free(BdrvChild *child);
27
- /* wait for all bottom halves to execute */
36
static void bdrv_replace_child_noperm(BdrvChild **child,
28
- }
37
- BlockDriverState *new_bs,
38
- bool free_empty_child);
39
+ BlockDriverState *new_bs);
40
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
41
BdrvChild *child,
42
Transaction *tran);
43
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvReplaceChildState {
44
BdrvChild *child;
45
BdrvChild **childp;
46
BlockDriverState *old_bs;
47
- bool free_empty_child;
48
} BdrvReplaceChildState;
49
50
static void bdrv_replace_child_commit(void *opaque)
51
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_commit(void *opaque)
52
BdrvReplaceChildState *s = opaque;
53
GLOBAL_STATE_CODE();
54
55
- if (s->free_empty_child && !s->child->bs) {
56
- bdrv_child_free(s->child);
57
- }
58
bdrv_unref(s->old_bs);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
62
* modify the BdrvChild * pointer we indirectly pass to it, i.e. it
63
* will not modify s->child. From that perspective, it does not matter
64
* whether we pass s->childp or &s->child.
65
+ * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
66
+ * pointer anyway (though it will in the future), so at this point it
67
+ * absolutely does not matter whether we pass s->childp or &s->child.)
68
* (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
69
* it here.
70
* (3) If new_bs is NULL, *s->childp will have been NULLed by
71
* bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
72
* must not pass a NULL *s->childp here.
73
+ * (TODO: In its current state, bdrv_replace_child_noperm() will not
74
+ * have NULLed *s->childp, so this does not apply yet. It will in the
75
+ * future.)
76
*
77
* So whether new_bs was NULL or not, we cannot pass s->childp here; and in
78
* any case, there is no reason to pass it anyway.
79
*/
80
- bdrv_replace_child_noperm(&s->child, s->old_bs, true);
81
- /*
82
- * The child was pre-existing, so s->old_bs must be non-NULL, and
83
- * s->child thus must not have been freed
84
- */
85
- assert(s->child != NULL);
86
- if (!new_bs) {
87
- /* As described above, *s->childp was cleared, so restore it */
88
- assert(s->childp != NULL);
89
- *s->childp = s->child;
90
- }
91
+ bdrv_replace_child_noperm(&s->child, s->old_bs);
92
bdrv_unref(new_bs);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
96
*
97
* The function doesn't update permissions, caller is responsible for this.
98
*
99
- * (*childp)->bs must not be NULL.
100
- *
101
* Note that if new_bs == NULL, @childp is stored in a state object attached
102
* to @tran, so that the old child can be reinstated in the abort handler.
103
* Therefore, if @new_bs can be NULL, @childp must stay valid until the
104
* transaction is committed or aborted.
105
*
106
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
107
- * freed (on commit). @free_empty_child should only be false if the
108
- * caller will free the BDrvChild themselves (which may be important
109
- * if this is in turn called in another transactional context).
110
+ * (TODO: The reinstating does not happen yet, but it will once
111
+ * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
112
*/
113
static void bdrv_replace_child_tran(BdrvChild **childp,
114
BlockDriverState *new_bs,
115
- Transaction *tran,
116
- bool free_empty_child)
117
+ Transaction *tran)
118
{
119
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
120
*s = (BdrvReplaceChildState) {
121
.child = *childp,
122
.childp = new_bs == NULL ? childp : NULL,
123
.old_bs = (*childp)->bs,
124
- .free_empty_child = free_empty_child,
125
};
126
tran_add(tran, &bdrv_replace_child_drv, s);
127
128
- /* The abort handler relies on this */
129
- assert(s->old_bs != NULL);
29
-
130
-
30
bdrv_detach_aio_context(bs);
131
if (new_bs) {
31
132
bdrv_ref(new_bs);
32
/* This function executes in the old AioContext so acquire the new one in
133
}
134
- /*
135
- * Pass free_empty_child=false, we will free the child (if
136
- * necessary) in bdrv_replace_child_commit() (if our
137
- * @free_empty_child parameter was true).
138
- */
139
- bdrv_replace_child_noperm(childp, new_bs, false);
140
+ bdrv_replace_child_noperm(childp, new_bs);
141
/* old_bs reference is transparently moved from *childp to @s */
142
}
143
144
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
145
return permissions[qapi_perm];
146
}
147
148
-/**
149
- * Replace (*childp)->bs by @new_bs.
150
- *
151
- * If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
152
- * generally cannot handle a BdrvChild with .bs == NULL, so clearing
153
- * BdrvChild.bs should generally immediately be followed by the
154
- * BdrvChild pointer being cleared as well.
155
- *
156
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
157
- * freed. @free_empty_child should only be false if the caller will
158
- * free the BdrvChild themselves (this may be important in a
159
- * transactional context, where it may only be freed on commit).
160
- */
161
static void bdrv_replace_child_noperm(BdrvChild **childp,
162
- BlockDriverState *new_bs,
163
- bool free_empty_child)
164
+ BlockDriverState *new_bs)
165
{
166
BdrvChild *child = *childp;
167
BlockDriverState *old_bs = child->bs;
168
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
169
}
170
171
child->bs = new_bs;
172
- if (!new_bs) {
173
- *childp = NULL;
174
- }
175
176
if (new_bs) {
177
assert_bdrv_graph_writable(new_bs);
178
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
179
bdrv_parent_drained_end_single(child);
180
drain_saldo++;
181
}
182
-
183
- if (free_empty_child && !child->bs) {
184
- bdrv_child_free(child);
185
- }
186
}
187
188
/**
189
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
190
BlockDriverState *bs = child->bs;
191
192
GLOBAL_STATE_CODE();
193
- /*
194
- * Pass free_empty_child=false, because we still need the child
195
- * for the AioContext operations on the parent below; those
196
- * BdrvChildClass methods all work on a BdrvChild object, so we
197
- * need to keep it as an empty shell (after this function, it will
198
- * not be attached to any parent, and it will not have a .bs).
199
- */
200
- bdrv_replace_child_noperm(s->child, NULL, false);
201
+ bdrv_replace_child_noperm(s->child, NULL);
202
203
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
204
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
205
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
206
207
bdrv_unref(bs);
208
bdrv_child_free(child);
209
+ *s->child = NULL;
210
}
211
212
static TransactionActionDrv bdrv_attach_child_common_drv = {
213
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
214
}
215
216
bdrv_ref(child_bs);
217
- bdrv_replace_child_noperm(&new_child, child_bs, true);
218
- /* child_bs was non-NULL, so new_child must not have been freed */
219
- assert(new_child != NULL);
220
+ bdrv_replace_child_noperm(&new_child, child_bs);
221
222
*child = new_child;
223
224
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild **childp)
225
BlockDriverState *old_bs = (*childp)->bs;
226
227
GLOBAL_STATE_CODE();
228
- bdrv_replace_child_noperm(childp, NULL, true);
229
+ bdrv_replace_child_noperm(childp, NULL);
230
+ bdrv_child_free(*childp);
231
232
if (old_bs) {
233
/*
234
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
235
}
236
237
if (child->bs) {
238
- /*
239
- * Pass free_empty_child=false, we will free the child in
240
- * bdrv_remove_filter_or_cow_child_commit()
241
- */
242
- bdrv_replace_child_tran(childp, NULL, tran, false);
243
+ bdrv_replace_child_tran(childp, NULL, tran);
244
}
245
246
s = g_new(BdrvRemoveFilterOrCowChild, 1);
247
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
248
.is_backing = (childp == &bs->backing),
249
};
250
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
251
+
252
+ *childp = NULL;
253
}
254
255
/*
256
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
257
* Passing a pointer to the local variable @c is fine here, because
258
* @to is not NULL, and so &c will not be attached to the transaction.
259
*/
260
- bdrv_replace_child_tran(&c, to, tran, true);
261
+ bdrv_replace_child_tran(&c, to, tran);
262
}
263
264
return 0;
265
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
266
bdrv_drained_begin(old_bs);
267
bdrv_drained_begin(new_bs);
268
269
- bdrv_replace_child_tran(&child, new_bs, tran, true);
270
- /* @new_bs must have been non-NULL, so @child must not have been freed */
271
- assert(child != NULL);
272
+ bdrv_replace_child_tran(&child, new_bs, tran);
273
274
found = g_hash_table_new(NULL, NULL);
275
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
33
--
276
--
34
2.20.1
277
2.37.3
35
36
diff view generated by jsdifflib
1
Now that bdrv_set_aio_context() works inside drained sections, it can
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
also use the real drain function instead of open coding something
2
3
similar.
3
That's a preparation to previously reverted
4
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
need it for a new approach.
6
7
This reverts commit 82b54cf51656bf3cd5ed1ac549e8a1085a0e3290.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-11-vsementsov@yandex-team.ru>
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
block.c | 81 +++++++--------------------------------------------------
8
1 file changed, 6 insertions(+), 9 deletions(-)
15
1 file changed, 10 insertions(+), 71 deletions(-)
9
16
10
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
11
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
12
--- a/block.c
19
--- a/block.c
13
+++ b/block.c
20
+++ b/block.c
14
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
15
bs->walking_aio_notifiers = false;
22
16
}
23
typedef struct BdrvReplaceChildState {
17
24
BdrvChild *child;
18
+/* The caller must own the AioContext lock for the old AioContext of bs, but it
25
- BdrvChild **childp;
19
+ * must not own the AioContext lock for new_context (unless new_context is
26
BlockDriverState *old_bs;
20
+ * the same as the current context of bs). */
27
} BdrvReplaceChildState;
21
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
28
29
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
30
BlockDriverState *new_bs = s->child->bs;
31
32
GLOBAL_STATE_CODE();
33
- /*
34
- * old_bs reference is transparently moved from @s to s->child.
35
- *
36
- * Pass &s->child here instead of s->childp, because:
37
- * (1) s->old_bs must be non-NULL, so bdrv_replace_child_noperm() will not
38
- * modify the BdrvChild * pointer we indirectly pass to it, i.e. it
39
- * will not modify s->child. From that perspective, it does not matter
40
- * whether we pass s->childp or &s->child.
41
- * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
42
- * pointer anyway (though it will in the future), so at this point it
43
- * absolutely does not matter whether we pass s->childp or &s->child.)
44
- * (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
45
- * it here.
46
- * (3) If new_bs is NULL, *s->childp will have been NULLed by
47
- * bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
48
- * must not pass a NULL *s->childp here.
49
- * (TODO: In its current state, bdrv_replace_child_noperm() will not
50
- * have NULLed *s->childp, so this does not apply yet. It will in the
51
- * future.)
52
- *
53
- * So whether new_bs was NULL or not, we cannot pass s->childp here; and in
54
- * any case, there is no reason to pass it anyway.
55
- */
56
+ /* old_bs reference is transparently moved from @s to @s->child */
57
bdrv_replace_child_noperm(&s->child, s->old_bs);
58
bdrv_unref(new_bs);
59
}
60
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
61
* Note: real unref of old_bs is done only on commit.
62
*
63
* The function doesn't update permissions, caller is responsible for this.
64
- *
65
- * Note that if new_bs == NULL, @childp is stored in a state object attached
66
- * to @tran, so that the old child can be reinstated in the abort handler.
67
- * Therefore, if @new_bs can be NULL, @childp must stay valid until the
68
- * transaction is committed or aborted.
69
- *
70
- * (TODO: The reinstating does not happen yet, but it will once
71
- * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
72
*/
73
-static void bdrv_replace_child_tran(BdrvChild **childp,
74
- BlockDriverState *new_bs,
75
+static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
76
Transaction *tran)
22
{
77
{
23
- AioContext *ctx = bdrv_get_aio_context(bs);
78
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
79
*s = (BdrvReplaceChildState) {
80
- .child = *childp,
81
- .childp = new_bs == NULL ? childp : NULL,
82
- .old_bs = (*childp)->bs,
83
+ .child = child,
84
+ .old_bs = child->bs,
85
};
86
tran_add(tran, &bdrv_replace_child_drv, s);
87
88
if (new_bs) {
89
bdrv_ref(new_bs);
90
}
91
- bdrv_replace_child_noperm(childp, new_bs);
92
- /* old_bs reference is transparently moved from *childp to @s */
93
+ bdrv_replace_child_noperm(&child, new_bs);
94
+ /* old_bs reference is transparently moved from @child to @s */
95
}
96
97
/*
98
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
99
100
typedef struct BdrvRemoveFilterOrCowChild {
101
BdrvChild *child;
102
- BlockDriverState *bs;
103
bool is_backing;
104
} BdrvRemoveFilterOrCowChild;
105
106
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
107
bdrv_child_free(s->child);
108
}
109
110
-static void bdrv_remove_filter_or_cow_child_clean(void *opaque)
111
-{
112
- BdrvRemoveFilterOrCowChild *s = opaque;
24
-
113
-
25
- if (ctx == new_context) {
114
- /* Drop the bs reference after the transaction is done */
26
+ if (bdrv_get_aio_context(bs) == new_context) {
115
- bdrv_unref(s->bs);
116
- g_free(s);
117
-}
118
-
119
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
120
.abort = bdrv_remove_filter_or_cow_child_abort,
121
.commit = bdrv_remove_filter_or_cow_child_commit,
122
- .clean = bdrv_remove_filter_or_cow_child_clean,
123
+ .clean = g_free,
124
};
125
126
/*
127
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
27
return;
128
return;
28
}
129
}
29
130
30
- aio_disable_external(ctx);
131
- /*
31
- bdrv_parent_drained_begin(bs, NULL, false);
132
- * Keep a reference to @bs so @childp will stay valid throughout the
32
- bdrv_drain(bs); /* ensure there are no in-flight requests */
133
- * transaction (required by bdrv_replace_child_tran())
134
- */
135
- bdrv_ref(bs);
136
if (child == bs->backing) {
137
childp = &bs->backing;
138
} else if (child == bs->file) {
139
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
140
}
141
142
if (child->bs) {
143
- bdrv_replace_child_tran(childp, NULL, tran);
144
+ bdrv_replace_child_tran(*childp, NULL, tran);
145
}
146
147
s = g_new(BdrvRemoveFilterOrCowChild, 1);
148
*s = (BdrvRemoveFilterOrCowChild) {
149
.child = child,
150
- .bs = bs,
151
.is_backing = (childp == &bs->backing),
152
};
153
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
154
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
155
{
156
BdrvChild *c, *next;
157
158
- assert(to != NULL);
159
GLOBAL_STATE_CODE();
160
161
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
162
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
163
c->name, from->node_name);
164
return -EPERM;
165
}
33
-
166
-
34
+ bdrv_drained_begin(bs);
167
- /*
35
bdrv_detach_aio_context(bs);
168
- * Passing a pointer to the local variable @c is fine here, because
36
169
- * @to is not NULL, and so &c will not be attached to the transaction.
37
/* This function executes in the old AioContext so acquire the new one in
170
- */
38
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
171
- bdrv_replace_child_tran(&c, to, tran);
39
*/
172
+ bdrv_replace_child_tran(c, to, tran);
40
aio_context_acquire(new_context);
173
}
41
bdrv_attach_aio_context(bs, new_context);
174
42
- bdrv_parent_drained_end(bs, NULL, false);
175
return 0;
43
- aio_enable_external(ctx);
176
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
44
+ bdrv_drained_end(bs);
177
*
45
aio_context_release(new_context);
178
* With @detach_subchain=true @to must be in a backing chain of @from. In this
46
}
179
* case backing link of the cow-parent of @to is removed.
47
180
- *
181
- * @to must not be NULL.
182
*/
183
static int bdrv_replace_node_common(BlockDriverState *from,
184
BlockDriverState *to,
185
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_common(BlockDriverState *from,
186
int ret;
187
188
GLOBAL_STATE_CODE();
189
- assert(to != NULL);
190
191
if (detach_subchain) {
192
assert(bdrv_chain_contains(from, to));
193
@@ -XXX,XX +XXX,XX @@ out:
194
return ret;
195
}
196
197
-/**
198
- * Replace node @from by @to (where neither may be NULL).
199
- */
200
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
201
Error **errp)
202
{
203
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
204
bdrv_drained_begin(old_bs);
205
bdrv_drained_begin(new_bs);
206
207
- bdrv_replace_child_tran(&child, new_bs, tran);
208
+ bdrv_replace_child_tran(child, new_bs, tran);
209
210
found = g_hash_table_new(NULL, NULL);
211
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
48
--
212
--
49
2.20.1
213
2.37.3
50
51
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
As it already said in the comment, we don't want to create loops in
3
That's a preparation to previously reverted
4
parent->child relations. So, when we try to append @to to @c, we should
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
check that @c is not in @to children subtree, and we should check it
5
need it for a new approach.
6
recursively, not only the first level. The patch provides BFS-based
7
search, to check the relations.
8
6
9
This is needed for further fleecing-hook filter usage: we need to
7
This reverts commit 562bda8bb41879eeda0bd484dd3d55134579b28e.
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
8
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-12-vsementsov@yandex-team.ru>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
13
---
18
block.c | 43 +++++++++++++++++++++++++++++++++++++------
14
block.c | 21 +++++++++------------
19
1 file changed, 37 insertions(+), 6 deletions(-)
15
1 file changed, 9 insertions(+), 12 deletions(-)
20
16
21
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/block.c
19
--- a/block.c
24
+++ b/block.c
20
+++ b/block.c
25
@@ -XXX,XX +XXX,XX @@ void bdrv_close_all(void)
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
26
22
BdrvChild *child,
27
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
23
Transaction *tran)
28
{
24
{
29
- BdrvChild *to_c;
25
- BdrvChild **childp;
30
+ GQueue *queue;
26
BdrvRemoveFilterOrCowChild *s;
31
+ GHashTable *found;
27
32
+ bool ret;
28
+ assert(child == bs->backing || child == bs->file);
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
+
29
+
52
+ ret = true;
30
if (!child) {
53
+ found = g_hash_table_new(NULL, NULL);
31
return;
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
}
32
}
76
33
77
- return true;
34
- if (child == bs->backing) {
78
+ g_queue_free(queue);
35
- childp = &bs->backing;
79
+ g_hash_table_destroy(found);
36
- } else if (child == bs->file) {
80
+
37
- childp = &bs->file;
81
+ return ret;
38
- } else {
39
- g_assert_not_reached();
40
- }
41
-
42
if (child->bs) {
43
- bdrv_replace_child_tran(*childp, NULL, tran);
44
+ bdrv_replace_child_tran(child, NULL, tran);
45
}
46
47
s = g_new(BdrvRemoveFilterOrCowChild, 1);
48
*s = (BdrvRemoveFilterOrCowChild) {
49
.child = child,
50
- .is_backing = (childp == &bs->backing),
51
+ .is_backing = (child == bs->backing),
52
};
53
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
54
55
- *childp = NULL;
56
+ if (s->is_backing) {
57
+ bs->backing = NULL;
58
+ } else {
59
+ bs->file = NULL;
60
+ }
82
}
61
}
83
62
84
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
63
/*
85
--
64
--
86
2.20.1
65
2.37.3
87
88
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
bdrv_check_perm in it's recursion checks each node in context of new
3
That's a preparation to previously reverted
4
permissions for one parent, because of nature of DFS. It works well,
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
while children subgraph of top-most updated node is a tree, i.e. it
5
need it for a new approach.
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
6
10
top
7
This reverts commit be64bbb0149748f3999c49b13976aafb8330ea86.
11
| \
12
| |
13
v v
14
A B
15
| |
16
v v
17
node
18
8
19
It will once check new permissions of node in context of new A
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
20
permissions and old B permissions and once visa-versa. It's a wrong way
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
and may lead to corruption of permission system. We may start with
11
Message-Id: <20220726201134.924743-13-vsementsov@yandex-team.ru>
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>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
13
---
35
include/block/block_int.h | 5 +++++
14
block.c | 23 +++++++++++------------
36
block.c | 27 ++++++++++++++++++++++++++-
15
1 file changed, 11 insertions(+), 12 deletions(-)
37
2 files changed, 31 insertions(+), 1 deletion(-)
38
16
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
17
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
19
--- a/block.c
58
+++ b/block.c
20
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
21
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
60
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
22
static bool bdrv_recurse_has_child(BlockDriverState *bs,
61
g_slist_free(ignore_children);
23
BlockDriverState *child);
62
24
63
- return ret;
25
-static void bdrv_replace_child_noperm(BdrvChild **child,
64
+ if (ret < 0) {
26
+static void bdrv_replace_child_noperm(BdrvChild *child,
65
+ return ret;
27
BlockDriverState *new_bs);
66
+ }
28
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
67
+
29
BdrvChild *child,
68
+ if (!c->has_backup_perm) {
30
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
69
+ c->has_backup_perm = true;
31
70
+ c->backup_perm = c->perm;
32
GLOBAL_STATE_CODE();
71
+ c->backup_shared_perm = c->shared_perm;
33
/* old_bs reference is transparently moved from @s to @s->child */
72
+ }
34
- bdrv_replace_child_noperm(&s->child, s->old_bs);
73
+ /*
35
+ bdrv_replace_child_noperm(s->child, s->old_bs);
74
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
36
bdrv_unref(new_bs);
75
+ * same child twice during check_perm procedure
76
+ */
77
+
78
+ c->perm = perm;
79
+ c->shared_perm = shared;
80
+
81
+ return 0;
82
}
37
}
83
38
84
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
39
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
40
if (new_bs) {
41
bdrv_ref(new_bs);
42
}
43
- bdrv_replace_child_noperm(&child, new_bs);
44
+ bdrv_replace_child_noperm(child, new_bs);
45
/* old_bs reference is transparently moved from @child to @s */
46
}
47
48
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
49
return permissions[qapi_perm];
50
}
51
52
-static void bdrv_replace_child_noperm(BdrvChild **childp,
53
+static void bdrv_replace_child_noperm(BdrvChild *child,
54
BlockDriverState *new_bs)
85
{
55
{
86
uint64_t cumulative_perms, cumulative_shared_perms;
56
- BdrvChild *child = *childp;
87
57
BlockDriverState *old_bs = child->bs;
88
+ c->has_backup_perm = false;
58
int new_bs_quiesce_counter;
89
+
59
int drain_saldo;
90
c->perm = perm;
60
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
91
c->shared_perm = shared;
61
BlockDriverState *bs = child->bs;
92
62
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
63
GLOBAL_STATE_CODE();
94
64
- bdrv_replace_child_noperm(s->child, NULL);
95
static void bdrv_child_abort_perm_update(BdrvChild *c)
65
+ bdrv_replace_child_noperm(child, NULL);
66
67
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
68
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
69
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
70
}
71
72
bdrv_ref(child_bs);
73
- bdrv_replace_child_noperm(&new_child, child_bs);
74
+ bdrv_replace_child_noperm(new_child, child_bs);
75
76
*child = new_child;
77
78
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
79
return 0;
80
}
81
82
-static void bdrv_detach_child(BdrvChild **childp)
83
+static void bdrv_detach_child(BdrvChild *child)
96
{
84
{
97
+ if (c->has_backup_perm) {
85
- BlockDriverState *old_bs = (*childp)->bs;
98
+ c->perm = c->backup_perm;
86
+ BlockDriverState *old_bs = child->bs;
99
+ c->shared_perm = c->backup_shared_perm;
87
100
+ c->has_backup_perm = false;
88
GLOBAL_STATE_CODE();
101
+ }
89
- bdrv_replace_child_noperm(childp, NULL);
102
+
90
- bdrv_child_free(*childp);
103
bdrv_abort_perm_update(c->bs);
91
+ bdrv_replace_child_noperm(child, NULL);
92
+ bdrv_child_free(child);
93
94
if (old_bs) {
95
/*
96
@@ -XXX,XX +XXX,XX @@ void bdrv_root_unref_child(BdrvChild *child)
97
GLOBAL_STATE_CODE();
98
99
child_bs = child->bs;
100
- bdrv_detach_child(&child);
101
+ bdrv_detach_child(child);
102
bdrv_unref(child_bs);
104
}
103
}
105
104
106
--
105
--
107
2.20.1
106
2.37.3
108
109
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Before this patch, bdrv_refresh_filename() is used in a pushing manner:
3
bs->file and bs->backing are a kind of duplication of part of
4
Whenever the BDS graph is modified, the parents of the modified edges
4
bs->children. But very useful diplication, so let's not drop them at
5
are supposed to be updated (recursively upwards). However, that is
5
all:)
6
nonviable, considering that we want child changes not to concern
6
7
parents.
7
We should manage bs->file and bs->backing in same place, where we
8
8
manage bs->children, to keep them in sync.
9
Also, in the long run we want a pull model anyway: Here, we would have a
9
10
bdrv_filename() function which returns a BDS's filename, freshly
10
Moreover, generic io paths are unprepared to BdrvChild without a bs, so
11
constructed.
11
it's double good to clear bs->file / bs->backing when we detach the
12
12
child.
13
This patch is an intermediate step. It adds bdrv_refresh_filename()
13
14
calls before every place a BDS.filename value is used. The only
14
Detach is simple: if we detach bs->file or bs->backing child, just
15
exceptions are protocol drivers that use their own filename, which
15
set corresponding field to NULL.
16
clearly would not profit from refreshing that filename before.
16
17
17
Attach is a bit more complicated. But we still can precisely detect
18
Also, bdrv_get_encrypted_filename() is removed along the way (as a user
18
should we set one of bs->file / bs->backing or not:
19
of BDS.filename), since it is completely unused.
19
20
20
- if role is BDRV_CHILD_COW, we definitely deal with bs->backing
21
In turn, all of the calls to bdrv_refresh_filename() before this patch
21
- else, if role is BDRV_CHILD_FILTERED (it must be also
22
are removed, because we no longer have to call this function on graph
22
BDRV_CHILD_PRIMARY), it's a filtered child. Use
23
changes.
23
bs->drv->filtered_child_is_backing to chose the pointer field to
24
24
modify.
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
- else, if role is BDRV_CHILD_PRIMARY, we deal with bs->file
26
Message-id: 20190201192935.18394-2-mreitz@redhat.com
26
- in all other cases, it's neither bs->backing nor bs->file. It's some
27
Reviewed-by: Eric Blake <eblake@redhat.com>
27
other child and we shouldn't care
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
29
OK. This change brings one more good thing: we can (and should) get rid
30
of all indirect pointers in the block-graph-change transactions:
31
32
bdrv_attach_child_common() stores BdrvChild** into transaction to clear
33
it on abort.
34
35
bdrv_attach_child_common() has two callers: bdrv_attach_child_noperm()
36
just pass-through this feature, bdrv_root_attach_child() doesn't need
37
the feature.
38
39
Look at bdrv_attach_child_noperm() callers:
40
- bdrv_attach_child() doesn't need the feature
41
- bdrv_set_file_or_backing_noperm() uses the feature to manage
42
bs->file and bs->backing, we don't want it anymore
43
- bdrv_append() uses the feature to manage bs->backing, again we
44
don't want it anymore
45
46
So, we should drop this stuff! Great!
47
48
We could probably keep BdrvChild** argument to keep the int return
49
value, but it seems not worth the complexity.
50
51
Finally, we now set .file / .backing automatically in generic code and
52
want to restring setting them by hand outside of .attach/.detach.
53
So, this patch cleanups all remaining places where they were set.
54
To find such places I use:
55
56
git grep '\->file ='
57
git grep '\->backing ='
58
git grep '&.*\<backing\>'
59
git grep '&.*\<file\>'
60
61
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
62
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
63
Message-Id: <20220726201134.924743-14-vsementsov@yandex-team.ru>
64
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
65
---
30
include/block/block.h | 1 -
66
include/block/block_int-common.h | 15 +-
31
block.c | 31 +++++++++++++++----------------
67
block.c | 234 ++++++++++++++-----------------
32
block/qapi.c | 4 ++++
68
block/raw-format.c | 4 +-
33
block/raw-format.c | 1 +
69
block/snapshot-access.c | 6 +-
34
block/replication.c | 2 --
70
block/snapshot.c | 1 -
35
block/vhdx-log.c | 1 +
71
tests/unit/test-bdrv-drain.c | 10 +-
36
block/vmdk.c | 6 ++++++
72
6 files changed, 126 insertions(+), 144 deletions(-)
37
blockdev.c | 8 ++++++++
73
38
qemu-img.c | 11 +++++++++--
74
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
9 files changed, 44 insertions(+), 21 deletions(-)
40
41
diff --git a/include/block/block.h b/include/block/block.h
42
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block.h
76
--- a/include/block/block_int-common.h
44
+++ b/include/block/block.h
77
+++ b/include/block/block_int-common.h
45
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
int64_t *cluster_offset,
79
QDict *full_open_options;
47
int64_t *cluster_bytes);
80
char exact_filename[PATH_MAX];
48
81
49
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
82
- BdrvChild *backing;
50
void bdrv_get_backing_filename(BlockDriverState *bs,
83
- BdrvChild *file;
51
char *filename, int filename_size);
84
-
52
void bdrv_get_full_backing_filename(BlockDriverState *bs,
85
/* I/O Limits */
86
BlockLimits bl;
87
88
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
89
* parent node of this node.
90
*/
91
BlockDriverState *inherits_from;
92
+
93
+ /*
94
+ * @backing and @file are some of @children or NULL. All these three fields
95
+ * (@file, @backing and @children) are modified only in
96
+ * bdrv_child_cb_attach() and bdrv_child_cb_detach().
97
+ *
98
+ * See also comment in include/block/block.h, to learn how backing and file
99
+ * are connected with BdrvChildRole.
100
+ */
101
QLIST_HEAD(, BdrvChild) children;
102
+ BdrvChild *backing;
103
+ BdrvChild *file;
104
+
105
QLIST_HEAD(, BdrvChild) parents;
106
107
QDict *options;
53
diff --git a/block.c b/block.c
108
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
109
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
110
--- a/block.c
56
+++ b/block.c
111
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
112
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
58
void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
113
59
Error **errp)
114
assert_bdrv_graph_writable(bs);
60
{
115
QLIST_INSERT_HEAD(&bs->children, child, next);
61
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
116
-
62
+ char *backed;
117
- if (child->role & BDRV_CHILD_COW) {
63
118
+ if (bs->drv->is_filter || (child->role & BDRV_CHILD_FILTERED)) {
64
+ bdrv_refresh_filename(bs);
119
+ /*
120
+ * Here we handle filters and block/raw-format.c when it behave like
121
+ * filter. They generally have a single PRIMARY child, which is also the
122
+ * FILTERED child, and that they may have multiple more children, which
123
+ * are neither PRIMARY nor FILTERED. And never we have a COW child here.
124
+ * So bs->file will be the PRIMARY child, unless the PRIMARY child goes
125
+ * into bs->backing on exceptional cases; and bs->backing will be
126
+ * nothing else.
127
+ */
128
+ assert(!(child->role & BDRV_CHILD_COW));
129
+ if (child->role & BDRV_CHILD_PRIMARY) {
130
+ assert(child->role & BDRV_CHILD_FILTERED);
131
+ assert(!bs->backing);
132
+ assert(!bs->file);
65
+
133
+
66
+ backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
134
+ if (bs->drv->filtered_child_is_backing) {
67
bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
135
+ bs->backing = child;
68
dest, sz, errp);
136
+ } else {
69
}
137
+ bs->file = child;
70
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
138
+ }
71
"node is used as backing hd of '%s'",
139
+ } else {
72
bdrv_get_device_or_node_name(parent));
140
+ assert(!(child->role & BDRV_CHILD_FILTERED));
73
141
+ }
74
+ bdrv_refresh_filename(backing_hd);
142
+ } else if (child->role & BDRV_CHILD_COW) {
143
+ assert(bs->drv->supports_backing);
144
+ assert(!(child->role & BDRV_CHILD_PRIMARY));
145
+ assert(!bs->backing);
146
+ bs->backing = child;
147
bdrv_backing_attach(child);
148
+ } else if (child->role & BDRV_CHILD_PRIMARY) {
149
+ assert(!bs->file);
150
+ bs->file = child;
151
}
152
153
bdrv_apply_subtree_drain(child, bs);
154
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
155
156
assert_bdrv_graph_writable(bs);
157
QLIST_REMOVE(child, next);
158
+ if (child == bs->backing) {
159
+ assert(child != bs->file);
160
+ bs->backing = NULL;
161
+ } else if (child == bs->file) {
162
+ bs->file = NULL;
163
+ }
164
}
165
166
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
167
@@ -XXX,XX +XXX,XX @@ open_failed:
168
bs->drv = NULL;
169
if (bs->file != NULL) {
170
bdrv_unref_child(bs, bs->file);
171
- bs->file = NULL;
172
+ assert(!bs->file);
173
}
174
g_free(bs->opaque);
175
bs->opaque = NULL;
176
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
177
}
178
179
typedef struct BdrvAttachChildCommonState {
180
- BdrvChild **child;
181
+ BdrvChild *child;
182
AioContext *old_parent_ctx;
183
AioContext *old_child_ctx;
184
} BdrvAttachChildCommonState;
185
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvAttachChildCommonState {
186
static void bdrv_attach_child_common_abort(void *opaque)
187
{
188
BdrvAttachChildCommonState *s = opaque;
189
- BdrvChild *child = *s->child;
190
- BlockDriverState *bs = child->bs;
191
+ BlockDriverState *bs = s->child->bs;
192
193
GLOBAL_STATE_CODE();
194
- bdrv_replace_child_noperm(child, NULL);
195
+ bdrv_replace_child_noperm(s->child, NULL);
196
197
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
198
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
199
}
200
201
- if (bdrv_child_get_parent_aio_context(child) != s->old_parent_ctx) {
202
+ if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
203
GSList *ignore;
204
205
/* No need to ignore `child`, because it has been detached already */
206
ignore = NULL;
207
- child->klass->can_set_aio_ctx(child, s->old_parent_ctx, &ignore,
208
- &error_abort);
209
+ s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
210
+ &error_abort);
211
g_slist_free(ignore);
212
213
ignore = NULL;
214
- child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
215
+ s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
216
g_slist_free(ignore);
217
}
218
219
bdrv_unref(bs);
220
- bdrv_child_free(child);
221
- *s->child = NULL;
222
+ bdrv_child_free(s->child);
223
}
224
225
static TransactionActionDrv bdrv_attach_child_common_drv = {
226
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
227
/*
228
* Common part of attaching bdrv child to bs or to blk or to job
229
*
230
- * Resulting new child is returned through @child.
231
- * At start *@child must be NULL.
232
- * @child is saved to a new entry of @tran, so that *@child could be reverted to
233
- * NULL on abort(). So referenced variable must live at least until transaction
234
- * end.
235
- *
236
* Function doesn't update permissions, caller is responsible for this.
237
+ *
238
+ * Returns new created child.
239
*/
240
-static int bdrv_attach_child_common(BlockDriverState *child_bs,
241
- const char *child_name,
242
- const BdrvChildClass *child_class,
243
- BdrvChildRole child_role,
244
- uint64_t perm, uint64_t shared_perm,
245
- void *opaque, BdrvChild **child,
246
- Transaction *tran, Error **errp)
247
+static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
248
+ const char *child_name,
249
+ const BdrvChildClass *child_class,
250
+ BdrvChildRole child_role,
251
+ uint64_t perm, uint64_t shared_perm,
252
+ void *opaque,
253
+ Transaction *tran, Error **errp)
254
{
255
BdrvChild *new_child;
256
AioContext *parent_ctx;
257
AioContext *child_ctx = bdrv_get_aio_context(child_bs);
258
259
- assert(child);
260
- assert(*child == NULL);
261
assert(child_class->get_parent_desc);
262
GLOBAL_STATE_CODE();
263
264
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
265
if (ret < 0) {
266
error_propagate(errp, local_err);
267
bdrv_child_free(new_child);
268
- return ret;
269
+ return NULL;
270
}
271
}
272
273
bdrv_ref(child_bs);
274
bdrv_replace_child_noperm(new_child, child_bs);
275
276
- *child = new_child;
277
-
278
BdrvAttachChildCommonState *s = g_new(BdrvAttachChildCommonState, 1);
279
*s = (BdrvAttachChildCommonState) {
280
- .child = child,
281
+ .child = new_child,
282
.old_parent_ctx = parent_ctx,
283
.old_child_ctx = child_ctx,
284
};
285
tran_add(tran, &bdrv_attach_child_common_drv, s);
286
287
- return 0;
288
+ return new_child;
289
}
290
291
/*
292
- * Variable referenced by @child must live at least until transaction end.
293
- * (see bdrv_attach_child_common() doc for details)
294
- *
295
* Function doesn't update permissions, caller is responsible for this.
296
*/
297
-static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
298
- BlockDriverState *child_bs,
299
- const char *child_name,
300
- const BdrvChildClass *child_class,
301
- BdrvChildRole child_role,
302
- BdrvChild **child,
303
- Transaction *tran,
304
- Error **errp)
305
+static BdrvChild *bdrv_attach_child_noperm(BlockDriverState *parent_bs,
306
+ BlockDriverState *child_bs,
307
+ const char *child_name,
308
+ const BdrvChildClass *child_class,
309
+ BdrvChildRole child_role,
310
+ Transaction *tran,
311
+ Error **errp)
312
{
313
- int ret;
314
uint64_t perm, shared_perm;
315
316
assert(parent_bs->drv);
317
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
318
if (bdrv_recurse_has_child(child_bs, parent_bs)) {
319
error_setg(errp, "Making '%s' a %s child of '%s' would create a cycle",
320
child_bs->node_name, child_name, parent_bs->node_name);
321
- return -EINVAL;
322
+ return NULL;
323
}
324
325
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
326
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
327
perm, shared_perm, &perm, &shared_perm);
328
329
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
330
- child_role, perm, shared_perm, parent_bs,
331
- child, tran, errp);
332
- if (ret < 0) {
333
- return ret;
334
- }
335
-
336
- return 0;
337
+ return bdrv_attach_child_common(child_bs, child_name, child_class,
338
+ child_role, perm, shared_perm, parent_bs,
339
+ tran, errp);
340
}
341
342
static void bdrv_detach_child(BdrvChild *child)
343
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
344
void *opaque, Error **errp)
345
{
346
int ret;
347
- BdrvChild *child = NULL;
348
+ BdrvChild *child;
349
Transaction *tran = tran_new();
350
351
GLOBAL_STATE_CODE();
352
353
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
354
+ child = bdrv_attach_child_common(child_bs, child_name, child_class,
355
child_role, perm, shared_perm, opaque,
356
- &child, tran, errp);
357
- if (ret < 0) {
358
+ tran, errp);
359
+ if (!child) {
360
+ ret = -EINVAL;
361
goto out;
362
}
363
364
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
365
366
out:
367
tran_finalize(tran, ret);
368
- /* child is unset on failure by bdrv_attach_child_common_abort() */
369
- assert((ret < 0) == !child);
370
371
bdrv_unref(child_bs);
372
- return child;
75
+
373
+
76
parent->open_flags &= ~BDRV_O_NO_BACKING;
374
+ return ret < 0 ? NULL : child;
77
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
375
}
78
backing_hd->filename);
376
79
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
377
/*
80
}
378
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
81
379
Error **errp)
82
if (file != NULL) {
380
{
83
+ bdrv_refresh_filename(blk_bs(file));
381
int ret;
84
filename = blk_bs(file)->filename;
382
- BdrvChild *child = NULL;
85
} else {
383
+ BdrvChild *child;
86
/*
384
Transaction *tran = tran_new();
87
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
385
88
bdrv_unref(backing_hd);
386
GLOBAL_STATE_CODE();
89
}
387
90
388
- ret = bdrv_attach_child_noperm(parent_bs, child_bs, child_name, child_class,
91
- bdrv_refresh_filename(bs);
389
- child_role, &child, tran, errp);
92
-
390
- if (ret < 0) {
391
+ child = bdrv_attach_child_noperm(parent_bs, child_bs, child_name,
392
+ child_class, child_role, tran, errp);
393
+ if (!child) {
394
+ ret = -EINVAL;
395
goto out;
396
}
397
398
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
399
93
out:
400
out:
94
bdrv_refresh_limits(bs, NULL);
401
tran_finalize(tran, ret);
95
}
402
- /* child is unset on failure by bdrv_attach_child_common_abort() */
96
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
403
- assert((ret < 0) == !child);
97
g_free(child_key_dot);
404
98
}
405
bdrv_unref(child_bs);
99
406
100
- bdrv_refresh_filename(bs);
407
- return child;
101
-
408
+ return ret < 0 ? NULL : child;
102
/* Check if any unknown options were used */
409
}
103
if (qdict_size(options) != 0) {
410
104
const QDictEntry *entry = qdict_first(options);
411
/* Callers must ensure that child->frozen is false. */
105
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
412
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
106
if (local_err != NULL) {
413
bool is_backing,
107
error_propagate(errp, local_err);
414
Transaction *tran, Error **errp)
108
} else {
415
{
109
+ bdrv_refresh_filename(reopen_state->bs);
416
- int ret = 0;
110
error_setg(errp, "failed while preparing to reopen image '%s'",
417
bool update_inherits_from =
111
reopen_state->bs->filename);
418
bdrv_inherits_from_recursive(child_bs, parent_bs);
112
}
419
BdrvChild *child = is_backing ? parent_bs->backing : parent_bs->file;
113
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
420
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
114
/* success - we can delete the intermediate states, and link top->base */
421
goto out;
115
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
422
}
116
* we've figured out how they should work. */
423
117
- backing_file_str = backing_file_str ? backing_file_str : base->filename;
424
- ret = bdrv_attach_child_noperm(parent_bs, child_bs,
118
+ if (!backing_file_str) {
425
- is_backing ? "backing" : "file",
119
+ bdrv_refresh_filename(base);
426
- &child_of_bds, role,
120
+ backing_file_str = base->filename;
427
- is_backing ? &parent_bs->backing :
428
- &parent_bs->file,
429
- tran, errp);
430
- if (ret < 0) {
431
- return ret;
432
+ child = bdrv_attach_child_noperm(parent_bs, child_bs,
433
+ is_backing ? "backing" : "file",
434
+ &child_of_bds, role,
435
+ tran, errp);
436
+ if (!child) {
437
+ return -EINVAL;
438
}
439
440
441
@@ -XXX,XX +XXX,XX @@ int bdrv_open_file_child(const char *filename,
442
443
/* commit_top and mirror_top don't use this function */
444
assert(!parent->drv->filtered_child_is_backing);
445
-
446
role = parent->drv->is_filter ?
447
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
448
449
- parent->file = bdrv_open_child(filename, options, bdref_key, parent,
450
- &child_of_bds, role, false, errp);
451
+ if (!bdrv_open_child(filename, options, bdref_key, parent,
452
+ &child_of_bds, role, false, errp))
453
+ {
454
+ return -EINVAL;
121
+ }
455
+ }
122
456
123
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
457
- return parent->file ? 0 : -EINVAL;
124
/* Check whether we are allowed to switch c from top to base */
458
+ return 0;
125
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
459
}
126
return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP;
460
127
}
461
/*
128
462
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
129
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
463
bdrv_unref_child(bs, child);
464
}
465
466
- bs->backing = NULL;
467
- bs->file = NULL;
468
+ assert(!bs->backing);
469
+ assert(!bs->file);
470
g_free(bs->opaque);
471
bs->opaque = NULL;
472
qatomic_set(&bs->copy_on_read, 0);
473
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
474
return ret;
475
}
476
477
-typedef struct BdrvRemoveFilterOrCowChild {
478
- BdrvChild *child;
479
- bool is_backing;
480
-} BdrvRemoveFilterOrCowChild;
481
-
482
-static void bdrv_remove_filter_or_cow_child_abort(void *opaque)
130
-{
483
-{
131
- if (bs->backing && bs->backing->bs->encrypted)
484
- BdrvRemoveFilterOrCowChild *s = opaque;
132
- return bs->backing_file;
485
- BlockDriverState *parent_bs = s->child->opaque;
133
- else if (bs->encrypted)
486
-
134
- return bs->filename;
487
- if (s->is_backing) {
135
- else
488
- parent_bs->backing = s->child;
136
- return NULL;
489
- } else {
490
- parent_bs->file = s->child;
491
- }
492
-
493
- /*
494
- * We don't have to restore child->bs here to undo bdrv_replace_child_tran()
495
- * because that function is transactionable and it registered own completion
496
- * entries in @tran, so .abort() for bdrv_replace_child_safe() will be
497
- * called automatically.
498
- */
137
-}
499
-}
138
-
500
-
139
void bdrv_get_backing_filename(BlockDriverState *bs,
501
static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
140
char *filename, int filename_size)
502
{
141
{
503
- BdrvRemoveFilterOrCowChild *s = opaque;
142
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
504
GLOBAL_STATE_CODE();
143
505
- bdrv_child_free(s->child);
144
is_protocol = path_has_protocol(backing_file);
506
+ bdrv_child_free(opaque);
145
507
}
146
+ /* This will recursively refresh everything in the backing chain */
508
147
+ bdrv_refresh_filename(bs);
509
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
148
+
510
- .abort = bdrv_remove_filter_or_cow_child_abort,
149
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
511
.commit = bdrv_remove_filter_or_cow_child_commit,
150
512
- .clean = g_free,
151
/* If either of the filename paths is actually a protocol, then
513
};
152
diff --git a/block/qapi.c b/block/qapi.c
514
153
index XXXXXXX..XXXXXXX 100644
515
/*
154
--- a/block/qapi.c
516
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
155
+++ b/block/qapi.c
517
BdrvChild *child,
156
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
518
Transaction *tran)
157
return NULL;
519
{
158
}
520
- BdrvRemoveFilterOrCowChild *s;
159
521
-
160
+ bdrv_refresh_filename(bs);
522
assert(child == bs->backing || child == bs->file);
161
+
523
162
info = g_malloc0(sizeof(*info));
524
if (!child) {
163
info->file = g_strdup(bs->filename);
525
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
164
info->ro = bs->read_only;
526
bdrv_replace_child_tran(child, NULL, tran);
165
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
527
}
528
529
- s = g_new(BdrvRemoveFilterOrCowChild, 1);
530
- *s = (BdrvRemoveFilterOrCowChild) {
531
- .child = child,
532
- .is_backing = (child == bs->backing),
533
- };
534
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
535
-
536
- if (s->is_backing) {
537
- bs->backing = NULL;
538
- } else {
539
- bs->file = NULL;
540
- }
541
+ tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
542
}
543
544
/*
545
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
546
Error **errp)
547
{
548
int ret;
549
+ BdrvChild *child;
550
Transaction *tran = tran_new();
551
552
GLOBAL_STATE_CODE();
553
554
assert(!bs_new->backing);
555
556
- ret = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
557
- &child_of_bds, bdrv_backing_role(bs_new),
558
- &bs_new->backing, tran, errp);
559
- if (ret < 0) {
560
+ child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
561
+ &child_of_bds, bdrv_backing_role(bs_new),
562
+ tran, errp);
563
+ if (!child) {
564
+ ret = -EINVAL;
166
goto out;
565
goto out;
167
}
566
}
168
567
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
568
diff --git a/block/raw-format.c b/block/raw-format.c
175
index XXXXXXX..XXXXXXX 100644
569
index XXXXXXX..XXXXXXX 100644
176
--- a/block/raw-format.c
570
--- a/block/raw-format.c
177
+++ b/block/raw-format.c
571
+++ b/block/raw-format.c
178
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
572
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
179
bs->file->bs->supported_zero_flags);
573
file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
180
574
}
181
if (bs->probed && !bdrv_is_read_only(bs)) {
575
182
+ bdrv_refresh_filename(bs->file->bs);
576
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
183
fprintf(stderr,
577
- file_role, false, errp);
184
"WARNING: Image format was not specified for '%s' and probing "
578
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
185
"guessed raw.\n"
579
+ file_role, false, errp);
186
diff --git a/block/replication.c b/block/replication.c
580
if (!bs->file) {
581
return -EINVAL;
582
}
583
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
187
index XXXXXXX..XXXXXXX 100644
584
index XXXXXXX..XXXXXXX 100644
188
--- a/block/replication.c
585
--- a/block/snapshot-access.c
189
+++ b/block/replication.c
586
+++ b/block/snapshot-access.c
190
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
587
@@ -XXX,XX +XXX,XX @@ static void snapshot_access_refresh_filename(BlockDriverState *bs)
191
if (ret == 0) {
588
static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags,
192
s->stage = BLOCK_REPLICATION_DONE;
589
Error **errp)
193
590
{
194
- /* refresh top bs's filename */
591
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
195
- bdrv_refresh_filename(bs);
592
- BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
196
s->active_disk = NULL;
593
- false, errp);
197
s->secondary_disk = NULL;
594
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
198
s->hidden_disk = NULL;
595
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
199
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
596
+ false, errp);
597
if (!bs->file) {
598
return -EINVAL;
599
}
600
diff --git a/block/snapshot.c b/block/snapshot.c
200
index XXXXXXX..XXXXXXX 100644
601
index XXXXXXX..XXXXXXX 100644
201
--- a/block/vhdx-log.c
602
--- a/block/snapshot.c
202
+++ b/block/vhdx-log.c
603
+++ b/block/snapshot.c
203
@@ -XXX,XX +XXX,XX @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
604
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
204
605
205
if (logs.valid) {
606
/* .bdrv_open() will re-attach it */
206
if (bs->read_only) {
607
bdrv_unref_child(bs, *fallback_ptr);
207
+ bdrv_refresh_filename(bs);
608
- *fallback_ptr = NULL;
208
ret = -EPERM;
609
209
error_setg(errp,
610
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
210
"VHDX image file '%s' opened read-only, but "
611
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
211
diff --git a/block/vmdk.c b/block/vmdk.c
612
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
212
index XXXXXXX..XXXXXXX 100644
613
index XXXXXXX..XXXXXXX 100644
213
--- a/block/vmdk.c
614
--- a/tests/unit/test-bdrv-drain.c
214
+++ b/block/vmdk.c
615
+++ b/tests/unit/test-bdrv-drain.c
215
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
616
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
216
extent->l1_table,
617
for (i = 0; i < 3; i++) {
217
l1_size);
618
if (i) {
218
if (ret < 0) {
619
/* Takes the reference to chain[i - 1] */
219
+ bdrv_refresh_filename(extent->file->bs);
620
- chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
220
error_setg_errno(errp, -ret,
621
- "chain", &chain_child_class,
221
"Could not read l1 table from extent '%s'",
622
- BDRV_CHILD_COW, &error_abort);
222
extent->file->bs->filename);
623
+ bdrv_attach_child(chain[i], chain[i - 1], "chain",
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
624
+ &chain_child_class, BDRV_CHILD_COW, &error_abort);
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
}
271
+ bdrv_refresh_filename(state->old_bs);
272
bdrv_img_create(new_image_file, format,
273
state->old_bs->filename,
274
state->old_bs->drv->format_name,
275
@@ -XXX,XX +XXX,XX @@ void qmp_block_stream(bool has_job_id, const char *job_id, const char *device,
276
goto out;
277
}
625
}
278
assert(bdrv_get_aio_context(base_bs) == aio_context);
626
}
279
+ bdrv_refresh_filename(base_bs);
627
280
base_name = base_bs->filename;
628
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
281
}
629
new_child_bs->total_sectors = 1;
282
630
283
@@ -XXX,XX +XXX,XX @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
631
bdrv_ref(old_child_bs);
284
goto out;
632
- parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
285
}
633
- &child_of_bds, BDRV_CHILD_COW,
286
} else if (has_top && top) {
634
- &error_abort);
287
+ /* This strcmp() is just a shortcut, there is no need to
635
+ bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds,
288
+ * refresh @bs's filename. If it mismatches,
636
+ BDRV_CHILD_COW, &error_abort);
289
+ * bdrv_find_backing_image() will do the refresh and may still
637
290
+ * return @bs. */
638
for (i = 0; i < old_drain_count; i++) {
291
if (strcmp(bs->filename, top) != 0) {
639
bdrv_drained_begin(old_child_bs);
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
}
348
349
+ bdrv_refresh_filename(bs);
350
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
351
: bs->filename;
352
out_real_path = g_malloc(PATH_MAX);
353
--
640
--
354
2.20.1
641
2.37.3
355
356
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
At this moment, QEMU attempts to create/load/delete snapshots
3
Now the indirection is not actually used, we can safely reduce it to
4
by using either an ID (id_str) or a name. The problem is that the code
4
simple pointer. For consistency do a bit of refactoring to get rid of
5
isn't consistent of whether the entered argument is an ID or a name,
5
_ptr suffixes that become meaningless.
6
causing unexpected behaviors.
7
6
8
For example, when creating snapshots via savevm <arg>, what happens is that
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
9
"arg" is treated as both name and id_str. In a guest without snapshots, create
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
a single snapshot via savevm:
9
Message-Id: <20220726201134.924743-15-vsementsov@yandex-team.ru>
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
94
---
11
---
95
block/snapshot.c | 5 +++--
12
block/snapshot.c | 38 ++++++++++++++++----------------------
96
hmp-commands.hx | 32 ++++++++++++++++++++------------
13
1 file changed, 16 insertions(+), 22 deletions(-)
97
2 files changed, 23 insertions(+), 14 deletions(-)
98
14
99
diff --git a/block/snapshot.c b/block/snapshot.c
15
diff --git a/block/snapshot.c b/block/snapshot.c
100
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
101
--- a/block/snapshot.c
17
--- a/block/snapshot.c
102
+++ b/block/snapshot.c
18
+++ b/block/snapshot.c
103
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
19
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
20
}
21
22
/**
23
- * Return a pointer to the child BDS pointer to which we can fall
24
+ * Return a pointer to child of given BDS to which we can fall
25
* back if the given BDS does not support snapshots.
26
* Return NULL if there is no BDS to (safely) fall back to.
27
- *
28
- * We need to return an indirect pointer because bdrv_snapshot_goto()
29
- * has to modify the BdrvChild pointer.
30
*/
31
-static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
32
+static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
33
{
34
- BdrvChild **fallback;
35
- BdrvChild *child = bdrv_primary_child(bs);
36
+ BdrvChild *fallback = bdrv_primary_child(bs);
37
+ BdrvChild *child;
38
39
/* We allow fallback only to primary child */
40
- if (!child) {
41
+ if (!fallback) {
42
return NULL;
104
}
43
}
105
for (i = 0; i < nb_sns; i++) {
44
- fallback = (child == bs->file ? &bs->file : &bs->backing);
106
sn = &sn_tab[i];
45
- assert(*fallback == child);
107
- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
46
108
+ if (!strcmp(sn->name, name)) {
47
/*
109
*sn_info = *sn;
48
* Check that there are no other children that would need to be
110
ret = 0;
49
* snapshotted. If there are, it is not safe to fall back to
111
break;
50
- * *fallback.
112
@@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
51
+ * fallback.
113
aio_context_acquire(ctx);
52
*/
114
if (bdrv_can_snapshot(bs) &&
53
QLIST_FOREACH(child, &bs->children, next) {
115
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
54
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
116
- ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
55
BDRV_CHILD_FILTERED) &&
117
+ ret = bdrv_snapshot_delete(bs, snapshot->id_str,
56
- child != *fallback)
118
+ snapshot->name, err);
57
+ child != fallback)
58
{
59
return NULL;
119
}
60
}
120
aio_context_release(ctx);
61
@@ -XXX,XX +XXX,XX @@ static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
121
if (ret < 0) {
62
122
diff --git a/hmp-commands.hx b/hmp-commands.hx
63
static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
123
index XXXXXXX..XXXXXXX 100644
64
{
124
--- a/hmp-commands.hx
65
- BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs);
125
+++ b/hmp-commands.hx
66
- return child_ptr ? (*child_ptr)->bs : NULL;
126
@@ -XXX,XX +XXX,XX @@ ETEXI
67
+ return child_bs(bdrv_snapshot_fallback_child(bs));
127
{
68
}
128
.name = "savevm",
69
129
.args_type = "name:s?",
70
int bdrv_can_snapshot(BlockDriverState *bs)
130
- .params = "[tag|id]",
71
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
131
- .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
72
Error **errp)
132
+ .params = "tag",
73
{
133
+ .help = "save a VM snapshot. If no tag is provided, a new snapshot is created",
74
BlockDriver *drv = bs->drv;
134
.cmd = hmp_savevm,
75
- BdrvChild **fallback_ptr;
135
},
76
+ BdrvChild *fallback;
136
77
int ret, open_ret;
137
STEXI
78
138
-@item savevm [@var{tag}|@var{id}]
79
GLOBAL_STATE_CODE();
139
+@item savevm @var{tag}
80
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
140
@findex savevm
81
return ret;
141
Create a snapshot of the whole virtual machine. If @var{tag} is
82
}
142
provided, it is used as human readable identifier. If there is already
83
143
-a snapshot with the same tag or ID, it is replaced. More info at
84
- fallback_ptr = bdrv_snapshot_fallback_ptr(bs);
144
+a snapshot with the same tag, it is replaced. More info at
85
- if (fallback_ptr) {
145
@ref{vm_snapshots}.
86
+ fallback = bdrv_snapshot_fallback_child(bs);
146
+
87
+ if (fallback) {
147
+Since 4.0, savevm stopped allowing the snapshot id to be set, accepting
88
QDict *options;
148
+only @var{tag} as parameter.
89
QDict *file_options;
149
ETEXI
90
Error *local_err = NULL;
150
91
- BlockDriverState *fallback_bs = (*fallback_ptr)->bs;
151
{
92
- char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name);
152
.name = "loadvm",
93
+ BlockDriverState *fallback_bs = fallback->bs;
153
.args_type = "name:s",
94
+ char *subqdict_prefix = g_strdup_printf("%s.", fallback->name);
154
- .params = "tag|id",
95
155
- .help = "restore a VM snapshot from its tag or id",
96
options = qdict_clone_shallow(bs->options);
156
+ .params = "tag",
97
157
+ .help = "restore a VM snapshot from its tag",
98
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
158
.cmd = hmp_loadvm,
99
qobject_unref(file_options);
159
.command_completion = loadvm_completion,
100
g_free(subqdict_prefix);
160
},
101
161
102
- /* Force .bdrv_open() below to re-attach fallback_bs on *fallback_ptr */
162
STEXI
103
- qdict_put_str(options, (*fallback_ptr)->name,
163
-@item loadvm @var{tag}|@var{id}
104
+ /* Force .bdrv_open() below to re-attach fallback_bs on fallback */
164
+@item loadvm @var{tag}
105
+ qdict_put_str(options, fallback->name,
165
@findex loadvm
106
bdrv_get_node_name(fallback_bs));
166
Set the whole virtual machine to the snapshot identified by the tag
107
167
-@var{tag} or the unique snapshot ID @var{id}.
108
/* Now close bs, apply the snapshot on fallback_bs, and re-open bs */
168
+@var{tag}.
109
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
169
+
110
}
170
+Since 4.0, loadvm stopped accepting snapshot id as parameter.
111
171
ETEXI
112
/* .bdrv_open() will re-attach it */
172
113
- bdrv_unref_child(bs, *fallback_ptr);
173
{
114
+ bdrv_unref_child(bs, fallback);
174
.name = "delvm",
115
175
.args_type = "name:s",
116
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
176
- .params = "tag|id",
117
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
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
--
118
--
197
2.20.1
119
2.37.3
198
199
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Besides being safe for arbitrary path lengths, after some follow-up
3
Now the function can remove any child, so give it more common name.
4
patches all callers will want a freshly allocated buffer anyway.
4
Drop assertions and drop bs argument which becomes unused. Function
5
would be reused in a further commit.
5
6
6
In the meantime, path_combine_deprecated() is added which has the same
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
interface as path_combine() had before this patch. All callers to that
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
function will be converted in follow-up patches.
9
Message-Id: <20220726201134.924743-16-vsementsov@yandex-team.ru>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block.c | 27 +++++++++------------------
13
1 file changed, 9 insertions(+), 18 deletions(-)
9
14
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
15
diff --git a/block.c b/block.c
37
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
38
--- a/block.c
17
--- a/block.c
39
+++ b/block.c
18
+++ b/block.c
40
@@ -XXX,XX +XXX,XX @@ int path_is_absolute(const char *path)
19
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
41
#endif
20
21
static void bdrv_replace_child_noperm(BdrvChild *child,
22
BlockDriverState *new_bs);
23
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
24
- BdrvChild *child,
25
- Transaction *tran);
26
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran);
27
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
28
Transaction *tran);
29
30
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
31
32
if (child) {
33
bdrv_unset_inherits_from(parent_bs, child, tran);
34
- bdrv_remove_file_or_backing_child(parent_bs, child, tran);
35
+ bdrv_remove_child(child, tran);
36
}
37
38
if (!child_bs) {
39
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
40
return ret;
42
}
41
}
43
42
44
-/* if filename is absolute, just copy it to dest. Otherwise, build a
43
-static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
45
+/* if filename is absolute, just return its duplicate. Otherwise, build a
44
+static void bdrv_remove_child_commit(void *opaque)
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
{
45
{
53
+ const char *protocol_stripped = NULL;
46
GLOBAL_STATE_CODE();
54
const char *p, *p1;
47
bdrv_child_free(opaque);
55
+ char *result;
48
}
56
int len;
49
57
50
-static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
58
- if (dest_size <= 0)
51
- .commit = bdrv_remove_filter_or_cow_child_commit,
59
- return;
52
+static TransactionActionDrv bdrv_remove_child_drv = {
60
if (path_is_absolute(filename)) {
53
+ .commit = bdrv_remove_child_commit,
61
- pstrcpy(dest, dest_size, filename);
54
};
62
- } else {
55
63
- const char *protocol_stripped = NULL;
56
-/*
64
+ return g_strdup(filename);
57
- * A function to remove backing or file child of @bs.
65
+ }
58
- * Function doesn't update permissions, caller is responsible for this.
66
59
- */
67
- if (path_has_protocol(base_path)) {
60
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
68
- protocol_stripped = strchr(base_path, ':');
61
- BdrvChild *child,
69
- if (protocol_stripped) {
62
- Transaction *tran)
70
- protocol_stripped++;
63
+/* Function doesn't update permissions, caller is responsible for this. */
71
- }
64
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran)
72
+ if (path_has_protocol(base_path)) {
65
{
73
+ protocol_stripped = strchr(base_path, ':');
66
- assert(child == bs->backing || child == bs->file);
74
+ if (protocol_stripped) {
67
-
75
+ protocol_stripped++;
68
if (!child) {
76
}
69
return;
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
}
70
}
117
+ len = p - base_path;
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
118
+
72
bdrv_replace_child_tran(child, NULL, tran);
119
+ result = g_malloc(len + strlen(filename) + 1);
73
}
120
+ memcpy(result, base_path, len);
74
121
+ strcpy(result + len, filename);
75
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
122
+
76
+ tran_add(tran, &bdrv_remove_child_drv, child);
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
}
77
}
134
78
135
/*
79
/*
136
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
80
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
137
error_setg(errp, "Cannot use relative backing file names for '%s'",
81
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
138
backed);
82
Transaction *tran)
139
} else {
83
{
140
- path_combine(dest, sz, backed, backing);
84
- bdrv_remove_file_or_backing_child(bs, bdrv_filter_or_cow_child(bs), tran);
141
+ path_combine_deprecated(dest, sz, backed, backing);
85
+ bdrv_remove_child(bdrv_filter_or_cow_child(bs), tran);
142
}
143
}
86
}
144
87
145
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
88
static int bdrv_replace_node_noperm(BlockDriverState *from,
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
--
89
--
182
2.20.1
90
2.37.3
183
184
diff view generated by jsdifflib
1
When a drained node changes its AioContext, we need to move its
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
aio_disable_external() to the new context, too.
3
2
4
Without this fix, drain_end will try to reenable the new context, which
3
Also here ->aio_context is read by I/O threads and written
5
has never been disabled, so an assertion failure is triggered.
4
under BQL.
6
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20221025084952.2139888-2-eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
---
11
---
10
block.c | 7 +++++++
12
block.c | 2 ++
11
1 file changed, 7 insertions(+)
13
1 file changed, 2 insertions(+)
12
14
13
diff --git a/block.c b/block.c
15
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
17
--- a/block.c
16
+++ b/block.c
18
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ void bdrv_detach_aio_context(BlockDriverState *bs)
19
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_aio_context(BlockDriverState *bs)
18
bdrv_detach_aio_context(child->bs);
20
if (bs->quiesce_counter) {
21
aio_enable_external(bs->aio_context);
19
}
22
}
20
23
+ assert_bdrv_graph_writable(bs);
21
+ if (bs->quiesce_counter) {
22
+ aio_enable_external(bs->aio_context);
23
+ }
24
bs->aio_context = NULL;
24
bs->aio_context = NULL;
25
}
25
}
26
26
27
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
28
return;
28
aio_disable_external(new_context);
29
}
29
}
30
30
31
+ if (bs->quiesce_counter) {
31
+ assert_bdrv_graph_writable(bs);
32
+ aio_disable_external(new_context);
33
+ }
34
+
35
bs->aio_context = new_context;
32
bs->aio_context = new_context;
36
33
37
QLIST_FOREACH(child, &bs->children, next) {
34
if (bs->drv && bs->drv->bdrv_attach_aio_context) {
38
--
35
--
39
2.20.1
36
2.37.3
40
41
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Currently, BlockDriver.bdrv_refresh_filename() is supposed to both
3
Simplify the way the aiocontext can be changed in a BDS graph.
4
refresh the filename (BDS.exact_filename) and set BDS.full_open_options.
4
There are currently two problems in bdrv_try_set_aio_context:
5
Now that we have generic code in the central bdrv_refresh_filename() for
5
- There is a confusion of AioContext locks taken and released, because
6
creating BDS.full_open_options, we can drop the latter part from all
6
we assume that old aiocontext is always taken and new one is
7
BlockDriver.bdrv_refresh_filename() implementations.
7
taken inside.
8
8
9
This also means that we can drop all of the existing default code for
9
- It doesn't look very safe to call bdrv_drained_begin while some
10
this from the global bdrv_refresh_filename() itself.
10
nodes have already switched to the new aiocontext and others haven't.
11
11
This could be especially dangerous because bdrv_drained_begin polls, so
12
Furthermore, we now have to call BlockDriver.bdrv_refresh_filename()
12
something else could be executed while graph is in an inconsistent
13
after having set BDS.full_open_options, because the block driver's
13
state.
14
implementation should now be allowed to depend on BDS.full_open_options
14
15
being set correctly.
15
Additional minor nitpick: can_set and set_ callbacks both traverse the
16
16
graph, both using the ignored list of visited nodes in a different way.
17
Finally, with this patch we can drop the @options parameter from
17
18
BlockDriver.bdrv_refresh_filename(); also, add a comment on this
18
Therefore, get rid of all of this and introduce a new callback,
19
function's purpose in block/block_int.h while touching its interface.
19
change_aio_context, that uses transactions to efficiently, cleanly
20
20
and most importantly safely change the aiocontext of a graph.
21
This completely obsoletes blklogwrite's implementation of
21
22
.bdrv_refresh_filename().
22
This new callback is a "merge" of the two previous ones:
23
23
- Just like can_set_aio_context, recursively traverses the graph.
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
Marks all nodes that are visited using a GList, and checks if
25
Message-id: 20190201192935.18394-25-mreitz@redhat.com
25
they *could* change the aio_context.
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
- For each node that passes the above check, drain it and add a new transaction
27
that implements a callback that effectively changes the aiocontext.
28
- Once done, the recursive function returns if *all* nodes can change
29
the AioContext. If so, commit the above transactions.
30
Regardless of the outcome, call transaction.clean() to undo all drains
31
done in the recursion.
32
- The transaction list is scanned only after all nodes are being drained, so
33
we are sure that they all are in the same context, and then
34
we switch their AioContext, concluding the drain only after all nodes
35
switched to the new AioContext. In this way we make sure that
36
bdrv_drained_begin() is always called under the old AioContext, and
37
bdrv_drained_end() under the new one.
38
- Because of the above, we don't need to release and re-acquire the
39
old AioContext every time, as everything is done once (and not
40
per-node drain and aiocontext change).
41
42
Note that the "change" API is not yet invoked anywhere.
43
44
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
45
Message-Id: <20221025084952.2139888-3-eesposit@redhat.com>
46
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
47
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
48
---
28
include/block/block_int.h | 6 +-
49
include/block/block-global-state.h | 6 +
29
block.c | 131 +++++++------------------------------
50
include/block/block_int-common.h | 3 +
30
block/blkdebug.c | 54 ++++++---------
51
block.c | 220 ++++++++++++++++++++++++++++-
31
block/blklogwrites.c | 22 -------
52
3 files changed, 228 insertions(+), 1 deletion(-)
32
block/blkverify.c | 16 +----
53
33
block/commit.c | 2 +-
54
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
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
55
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
56
--- a/include/block/block-global-state.h
47
+++ b/include/block/block_int.h
57
+++ b/include/block/block-global-state.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
58
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
49
Error **errp);
59
GSList **ignore, Error **errp);
50
int (*bdrv_make_empty)(BlockDriverState *bs);
60
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
51
61
52
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
62
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
53
+ /*
63
+ GSList **visited, Transaction *tran,
54
+ * Refreshes the bs->exact_filename field. If that is impossible,
64
+ Error **errp);
55
+ * bs->exact_filename has to be left empty.
65
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
56
+ */
66
+ BdrvChild *ignore_child, Error **errp);
57
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
67
+
68
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
69
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
70
71
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-common.h
74
+++ b/include/block/block_int-common.h
75
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
76
GSList **ignore, Error **errp);
77
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
78
79
+ bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
80
+ GSList **visited, Transaction *tran, Error **errp);
81
+
82
AioContext *(*get_parent_aio_context)(BdrvChild *child);
58
83
59
/*
84
/*
60
* Gathers the open options for all children into @target.
61
diff --git a/block.c b/block.c
85
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
86
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
87
--- a/block.c
64
+++ b/block.c
88
+++ b/block.c
65
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
89
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
66
return found_any;
90
91
static bool bdrv_backing_overridden(BlockDriverState *bs);
92
93
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
94
+ GSList **visited, Transaction *tran,
95
+ Error **errp);
96
+
97
/* If non-zero, use only whitelisted block drivers */
98
static int use_bdrv_whitelist;
99
100
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
101
* must not own the AioContext lock for new_context (unless new_context is the
102
* same as the current context of bs).
103
*
104
- * @ignore will accumulate all visited BdrvChild object. The caller is
105
+ * @ignore will accumulate all visited BdrvChild objects. The caller is
106
* responsible for freeing the list afterwards.
107
*/
108
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
109
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
110
return true;
67
}
111
}
68
112
69
-static bool append_open_options(QDict *d, BlockDriverState *bs)
113
+typedef struct BdrvStateSetAioContext {
70
-{
114
+ AioContext *new_ctx;
71
- const QDictEntry *entry;
115
+ BlockDriverState *bs;
72
- QemuOptDesc *desc;
116
+} BdrvStateSetAioContext;
73
- bool found_any = false;
117
+
74
-
118
+static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
75
- for (entry = qdict_first(bs->options); entry;
119
+ GSList **visited, Transaction *tran,
76
- entry = qdict_next(bs->options, entry))
120
+ Error **errp)
77
- {
121
+{
78
- /* Exclude all non-driver-specific options */
122
+ GLOBAL_STATE_CODE();
79
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
123
+ if (g_slist_find(*visited, c)) {
80
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
124
+ return true;
81
- break;
125
+ }
82
- }
126
+ *visited = g_slist_prepend(*visited, c);
83
- }
127
+
84
- if (desc->name) {
128
+ /*
85
- continue;
129
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
86
- }
130
+ * tolerate any AioContext changes
87
-
131
+ */
88
- qdict_put_obj(d, qdict_entry_key(entry),
132
+ if (!c->klass->change_aio_ctx) {
89
- qobject_ref(qdict_entry_value(entry)));
133
+ char *user = bdrv_child_user_desc(c);
90
- found_any = true;
134
+ error_setg(errp, "Changing iothreads is not supported by %s", user);
91
- }
135
+ g_free(user);
92
-
136
+ return false;
93
- return found_any;
137
+ }
94
-}
138
+ if (!c->klass->change_aio_ctx(c, ctx, visited, tran, errp)) {
95
-
139
+ assert(!errp || *errp);
96
/* Note: This function may return false positives; it may return true
140
+ return false;
97
* even if opening the backing file specified by bs's image header
141
+ }
98
* would result in exactly bs->backing. */
142
+ return true;
99
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
143
+}
100
BdrvChild *child;
144
+
101
QDict *opts;
145
bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
102
bool backing_overridden;
146
GSList **ignore, Error **errp)
103
+ bool generate_json_filename; /* Whether our default implementation should
147
{
104
+ fill exact_filename (false) or not (true) */
148
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
105
149
return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
106
if (!drv) {
150
}
107
return;
151
108
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
152
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
109
backing_overridden = false;
153
+ GSList **visited, Transaction *tran,
110
}
154
+ Error **errp)
111
155
+{
112
- if (drv->bdrv_refresh_filename) {
156
+ GLOBAL_STATE_CODE();
113
- /* Obsolete information is of no use here, so drop the old file name
157
+ if (g_slist_find(*visited, c)) {
114
- * information before refreshing it */
158
+ return true;
115
- bs->exact_filename[0] = '\0';
159
+ }
116
- if (bs->full_open_options) {
160
+ *visited = g_slist_prepend(*visited, c);
117
- qobject_unref(bs->full_open_options);
161
+ return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
118
- bs->full_open_options = NULL;
162
+}
119
- }
163
+
120
-
164
/* @ignore will accumulate all visited BdrvChild object. The caller is
121
- opts = qdict_new();
165
* responsible for freeing the list afterwards. */
122
- append_open_options(opts, bs);
166
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
123
- drv->bdrv_refresh_filename(bs, opts);
167
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
124
- qobject_unref(opts);
168
return true;
125
- } else if (bs->file) {
169
}
126
- /* Try to reconstruct valid information from the underlying file */
170
127
- bool has_open_options;
171
+static void bdrv_set_aio_context_clean(void *opaque)
128
-
172
+{
129
- bs->exact_filename[0] = '\0';
173
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
130
- if (bs->full_open_options) {
174
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
131
- qobject_unref(bs->full_open_options);
175
+
132
- bs->full_open_options = NULL;
176
+ /* Paired with bdrv_drained_begin in bdrv_change_aio_context() */
133
- }
177
+ bdrv_drained_end(bs);
134
-
178
+
135
- opts = qdict_new();
179
+ g_free(state);
136
- has_open_options = append_open_options(opts, bs);
180
+}
137
- has_open_options |= backing_overridden;
181
+
138
-
182
+static void bdrv_set_aio_context_commit(void *opaque)
139
- /* If no specific options have been given for this BDS, the filename of
183
+{
140
- * the underlying file should suffice for this one as well */
184
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
141
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
185
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
142
- strcpy(bs->exact_filename, bs->file->bs->exact_filename);
186
+ AioContext *new_context = state->new_ctx;
143
- }
187
+ AioContext *old_context = bdrv_get_aio_context(bs);
144
- /* Reconstructing the full options QDict is simple for most format block
188
+ assert_bdrv_graph_writable(bs);
145
- * drivers, as long as the full options are known for the underlying
189
+
146
- * file BDS. The full options QDict of that file BDS should somehow
190
+ /*
147
- * contain a representation of the filename, therefore the following
191
+ * Take the old AioContex when detaching it from bs.
148
- * suffices without querying the (exact_)filename of this BDS. */
192
+ * At this point, new_context lock is already acquired, and we are now
149
- if (bs->file->bs->full_open_options &&
193
+ * also taking old_context. This is safe as long as bdrv_detach_aio_context
150
- (!bs->backing || bs->backing->bs->full_open_options))
194
+ * does not call AIO_POLL_WHILE().
151
- {
195
+ */
152
- qdict_put_str(opts, "driver", drv->format_name);
196
+ if (old_context != qemu_get_aio_context()) {
153
- qdict_put(opts, "file",
197
+ aio_context_acquire(old_context);
154
- qobject_ref(bs->file->bs->full_open_options));
198
+ }
155
-
199
+ bdrv_detach_aio_context(bs);
156
- if (bs->backing) {
200
+ if (old_context != qemu_get_aio_context()) {
157
- qdict_put(opts, "backing",
201
+ aio_context_release(old_context);
158
- qobject_ref(bs->backing->bs->full_open_options));
202
+ }
159
- } else if (backing_overridden) {
203
+ bdrv_attach_aio_context(bs, new_context);
160
- qdict_put_null(opts, "backing");
204
+}
161
- }
205
+
162
-
206
+static TransactionActionDrv set_aio_context = {
163
- bs->full_open_options = opts;
207
+ .commit = bdrv_set_aio_context_commit,
164
- } else {
208
+ .clean = bdrv_set_aio_context_clean,
165
- qobject_unref(opts);
209
+};
166
- }
210
+
167
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
211
+/*
168
- /* There is no underlying file BDS (at least referenced by BDS.file),
212
+ * Changes the AioContext used for fd handlers, timers, and BHs by this
169
- * so the full options QDict should be equal to the options given
213
+ * BlockDriverState and all its children and parents.
170
- * specifically for this block device when it was opened (plus the
214
+ *
171
- * driver specification).
215
+ * Must be called from the main AioContext.
172
- * Because those options don't change, there is no need to update
216
+ *
173
- * full_open_options when it's already set. */
217
+ * The caller must own the AioContext lock for the old AioContext of bs, but it
174
-
218
+ * must not own the AioContext lock for new_context (unless new_context is the
175
- opts = qdict_new();
219
+ * same as the current context of bs).
176
- append_open_options(opts, bs);
220
+ *
177
- qdict_put_str(opts, "driver", drv->format_name);
221
+ * @visited will accumulate all visited BdrvChild objects. The caller is
178
-
222
+ * responsible for freeing the list afterwards.
179
- if (bs->exact_filename[0]) {
223
+ */
180
- /* This may not work for all block protocol drivers (some may
224
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
181
- * require this filename to be parsed), but we have to find some
225
+ GSList **visited, Transaction *tran,
182
- * default solution here, so just include it. If some block driver
226
+ Error **errp)
183
- * does not support pure options without any filename at all or
227
+{
184
- * needs some special format of the options QDict, it needs to
228
+ BdrvChild *c;
185
- * implement the driver-specific bdrv_refresh_filename() function.
229
+ BdrvStateSetAioContext *state;
186
- */
230
+
187
- qdict_put_str(opts, "filename", bs->exact_filename);
231
+ GLOBAL_STATE_CODE();
188
- }
232
+
189
-
233
+ if (bdrv_get_aio_context(bs) == ctx) {
190
- bs->full_open_options = opts;
234
+ return true;
191
- }
235
+ }
192
-
236
+
193
/* Gather the options QDict */
237
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
194
opts = qdict_new();
238
+ if (!bdrv_parent_change_aio_context(c, ctx, visited, tran, errp)) {
195
- append_strong_runtime_options(opts, bs);
239
+ return false;
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
+ }
240
+ }
221
+ }
241
+ }
222
+
242
+
223
if (bs->exact_filename[0]) {
243
+ QLIST_FOREACH(c, &bs->children, next) {
224
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
244
+ if (!bdrv_child_change_aio_context(c, ctx, visited, tran, errp)) {
225
} else {
245
+ return false;
226
diff --git a/block/blkdebug.c b/block/blkdebug.c
246
+ }
227
index XXXXXXX..XXXXXXX 100644
247
+ }
228
--- a/block/blkdebug.c
248
+
229
+++ b/block/blkdebug.c
249
+ state = g_new(BdrvStateSetAioContext, 1);
230
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
250
+ *state = (BdrvStateSetAioContext) {
231
return bdrv_getlength(bs->file->bs);
251
+ .new_ctx = ctx,
232
}
252
+ .bs = bs,
233
253
+ };
234
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
254
+
235
+static void blkdebug_refresh_filename(BlockDriverState *bs)
255
+ /* Paired with bdrv_drained_end in bdrv_set_aio_context_clean() */
256
+ bdrv_drained_begin(bs);
257
+
258
+ tran_add(tran, &set_aio_context, state);
259
+
260
+ return true;
261
+}
262
+
263
int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
264
BdrvChild *ignore_child, Error **errp)
236
{
265
{
237
BDRVBlkdebugState *s = bs->opaque;
266
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
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;
257
}
258
259
- if (!force_json && bs->file->bs->exact_filename[0]) {
260
- int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
261
- "blkdebug:%s:%s", s->config_file ?: "",
262
- bs->file->bs->exact_filename);
263
- if (ret >= sizeof(bs->exact_filename)) {
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;
267
return 0;
454
}
268
}
455
269
456
-static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
270
+/*
457
+static void nfs_refresh_filename(BlockDriverState *bs)
271
+ * Change bs's and recursively all of its parents' and children's AioContext
272
+ * to the given new context, returning an error if that isn't possible.
273
+ *
274
+ * If ignore_child is not NULL, that child (and its subgraph) will not
275
+ * be touched.
276
+ *
277
+ * This function still requires the caller to take the bs current
278
+ * AioContext lock, otherwise draining will fail since AIO_WAIT_WHILE
279
+ * assumes the lock is always held if bs is in another AioContext.
280
+ * For the same reason, it temporarily also holds the new AioContext, since
281
+ * bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
282
+ * Therefore the new AioContext lock must not be taken by the caller.
283
+ */
284
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
285
+ BdrvChild *ignore_child, Error **errp)
286
+{
287
+ Transaction *tran;
288
+ GSList *visited;
289
+ int ret;
290
+ AioContext *old_context = bdrv_get_aio_context(bs);
291
+ GLOBAL_STATE_CODE();
292
+
293
+ /*
294
+ * Recursion phase: go through all nodes of the graph.
295
+ * Take care of checking that all nodes support changing AioContext
296
+ * and drain them, builing a linear list of callbacks to run if everything
297
+ * is successful (the transaction itself).
298
+ */
299
+ tran = tran_new();
300
+ visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
301
+ ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
302
+ g_slist_free(visited);
303
+
304
+ /*
305
+ * Linear phase: go through all callbacks collected in the transaction.
306
+ * Run all callbacks collected in the recursion to switch all nodes
307
+ * AioContext lock (transaction commit), or undo all changes done in the
308
+ * recursion (transaction abort).
309
+ */
310
+
311
+ if (!ret) {
312
+ /* Just run clean() callbacks. No AioContext changed. */
313
+ tran_abort(tran);
314
+ return -EPERM;
315
+ }
316
+
317
+ /*
318
+ * Release old AioContext, it won't be needed anymore, as all
319
+ * bdrv_drained_begin() have been called already.
320
+ */
321
+ if (qemu_get_aio_context() != old_context) {
322
+ aio_context_release(old_context);
323
+ }
324
+
325
+ /*
326
+ * Acquire new AioContext since bdrv_drained_end() is going to be called
327
+ * after we switched all nodes in the new AioContext, and the function
328
+ * assumes that the lock of the bs is always taken.
329
+ */
330
+ if (qemu_get_aio_context() != ctx) {
331
+ aio_context_acquire(ctx);
332
+ }
333
+
334
+ tran_commit(tran);
335
+
336
+ if (qemu_get_aio_context() != ctx) {
337
+ aio_context_release(ctx);
338
+ }
339
+
340
+ /* Re-acquire the old AioContext, since the caller takes and releases it. */
341
+ if (qemu_get_aio_context() != old_context) {
342
+ aio_context_acquire(old_context);
343
+ }
344
+
345
+ return 0;
346
+}
347
+
348
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
349
Error **errp)
458
{
350
{
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;
530
+ }
531
}
532
533
- qdict_put_str(opts, "driver", bs->drv->format_name);
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;
566
+ }
567
}
568
569
- qdict_put_str(opts, "driver", bs->drv->format_name);
570
- bs->full_open_options = qobject_ref(opts);
571
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
572
+ bs->drv->format_name);
573
}
574
575
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
576
diff --git a/block/quorum.c b/block/quorum.c
577
index XXXXXXX..XXXXXXX 100644
578
--- a/block/quorum.c
579
+++ b/block/quorum.c
580
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
581
bdrv_drained_end(bs);
582
}
583
584
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
585
-{
586
- BDRVQuorumState *s = bs->opaque;
587
- QDict *opts;
588
- QList *children;
589
- int i;
590
-
591
- for (i = 0; i < s->num_children; i++) {
592
- if (!s->children[i]->bs->full_open_options) {
593
- return;
594
- }
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
641
--- a/tests/qemu-iotests/228.out
642
+++ b/tests/qemu-iotests/228.out
643
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
644
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
645
{"return": {}}
646
647
-bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
648
+bs->filename: TEST_DIR/PID-top.img
649
bs->backing_file: TEST_DIR/PID-base.img
650
bs->backing->bs->filename: TEST_DIR/PID-base.img
651
652
--
351
--
653
2.20.1
352
2.37.3
654
655
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Make bdrv_get_full_backing_filename_from_filename() return an allocated
3
Minor performance improvement, but given that we have hash tables
4
string instead of placing the result in a caller-provided buffer.
4
available, avoid iterating in the visited nodes list every time just
5
to check if a node has been already visited.
5
6
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
The data structure is not actually a proper hash map, but an hash set,
7
Message-id: 20190201192935.18394-11-mreitz@redhat.com
8
as we are just adding nodes and not key,value pairs.
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
10
Suggested-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-4-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
15
---
10
include/block/block.h | 7 +++---
16
include/block/block-global-state.h | 2 +-
11
block.c | 53 ++++++++++++++++++++++++++++++-------------
17
include/block/block_int-common.h | 3 ++-
12
block/vmdk.c | 10 ++++----
18
block.c | 28 ++++++++++++++++------------
13
qemu-img.c | 12 ++++------
19
3 files changed, 19 insertions(+), 14 deletions(-)
14
4 files changed, 49 insertions(+), 33 deletions(-)
15
20
16
diff --git a/include/block/block.h b/include/block/block.h
21
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
23
--- a/include/block/block-global-state.h
19
+++ b/include/block/block.h
24
+++ b/include/block/block-global-state.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
25
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
21
char *filename, int filename_size);
26
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
22
void bdrv_get_full_backing_filename(BlockDriverState *bs,
27
23
char *dest, size_t sz, Error **errp);
28
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
24
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
29
- GSList **visited, Transaction *tran,
25
- const char *backing,
30
+ GHashTable *visited, Transaction *tran,
26
- char *dest, size_t sz,
31
Error **errp);
27
- Error **errp);
32
int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
28
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
33
BdrvChild *ignore_child, Error **errp);
29
+ const char *backing,
34
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
30
+ Error **errp);
35
index XXXXXXX..XXXXXXX 100644
31
36
--- a/include/block/block_int-common.h
32
int path_has_protocol(const char *path);
37
+++ b/include/block/block_int-common.h
33
int path_is_absolute(const char *path);
38
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
39
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
40
41
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
42
- GSList **visited, Transaction *tran, Error **errp);
43
+ GHashTable *visited, Transaction *tran,
44
+ Error **errp);
45
46
AioContext *(*get_parent_aio_context)(BdrvChild *child);
47
34
diff --git a/block.c b/block.c
48
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
50
--- a/block.c
37
+++ b/block.c
51
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ fail:
52
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
39
return -EACCES;
53
static bool bdrv_backing_overridden(BlockDriverState *bs);
54
55
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
56
- GSList **visited, Transaction *tran,
57
+ GHashTable *visited, Transaction *tran,
58
Error **errp);
59
60
/* If non-zero, use only whitelisted block drivers */
61
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvStateSetAioContext {
62
} BdrvStateSetAioContext;
63
64
static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
65
- GSList **visited, Transaction *tran,
66
+ GHashTable *visited,
67
+ Transaction *tran,
68
Error **errp)
69
{
70
GLOBAL_STATE_CODE();
71
- if (g_slist_find(*visited, c)) {
72
+ if (g_hash_table_contains(visited, c)) {
73
return true;
74
}
75
- *visited = g_slist_prepend(*visited, c);
76
+ g_hash_table_add(visited, c);
77
78
/*
79
* A BdrvChildClass that doesn't handle AioContext changes cannot
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
40
}
81
}
41
82
42
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
83
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
43
- const char *backing,
84
- GSList **visited, Transaction *tran,
44
- char *dest, size_t sz,
85
+ GHashTable *visited, Transaction *tran,
45
- Error **errp)
86
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
{
87
{
59
- if (backing[0] == '\0' || path_has_protocol(backing) ||
88
GLOBAL_STATE_CODE();
60
- path_is_absolute(backing))
89
- if (g_slist_find(*visited, c)) {
61
- {
90
+ if (g_hash_table_contains(visited, c)) {
62
- pstrcpy(dest, sz, backing);
91
return true;
63
+ if (backing[0] == '\0') {
64
+ return NULL;
65
+ } else if (path_has_protocol(backing) || path_is_absolute(backing)) {
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
}
92
}
93
- *visited = g_slist_prepend(*visited, c);
94
+ g_hash_table_add(visited, c);
95
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
75
}
96
}
76
97
77
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
98
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv set_aio_context = {
99
* responsible for freeing the list afterwards.
100
*/
101
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
102
- GSList **visited, Transaction *tran,
103
+ GHashTable *visited, Transaction *tran,
78
Error **errp)
104
Error **errp)
79
{
105
{
80
char *backed;
106
BdrvChild *c;
81
+ char *full_name;
107
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
82
+ Error *local_error = NULL;
108
BdrvChild *ignore_child, Error **errp)
83
109
{
84
bdrv_refresh_filename(bs);
110
Transaction *tran;
85
111
- GSList *visited;
86
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
112
+ GHashTable *visited;
87
- bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
113
int ret;
88
- dest, sz, errp);
114
AioContext *old_context = bdrv_get_aio_context(bs);
89
+
115
GLOBAL_STATE_CODE();
90
+ full_name = bdrv_get_full_backing_filename_from_filename(backed,
116
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
91
+ bs->backing_file,
117
* is successful (the transaction itself).
92
+ &local_error);
118
*/
93
+ if (full_name) {
119
tran = tran_new();
94
+ pstrcpy(dest, sz, full_name);
120
- visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
95
+ g_free(full_name);
121
- ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
96
+ } else if (local_error) {
122
- g_slist_free(visited);
97
+ error_propagate(errp, local_error);
123
+ visited = g_hash_table_new(NULL, NULL);
98
+ } else if (sz > 0) {
124
+ if (ignore_child) {
99
+ *dest = '\0';
125
+ g_hash_table_add(visited, ignore_child);
100
+ }
126
+ }
101
}
127
+ ret = bdrv_change_aio_context(bs, ctx, visited, tran, errp);
102
128
+ g_hash_table_destroy(visited);
103
void bdrv_register(BlockDriver *bdrv)
129
104
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
130
/*
105
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
131
* Linear phase: go through all callbacks collected in the transaction.
106
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
107
BlockDriverState *bs;
108
- char *full_backing = g_new0(char, PATH_MAX);
109
+ char *full_backing;
110
int back_flags;
111
QDict *backing_options = NULL;
112
113
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
114
- full_backing, PATH_MAX,
115
- &local_err);
116
+ full_backing =
117
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
118
+ &local_err);
119
if (local_err) {
120
- g_free(full_backing);
121
goto out;
122
}
123
+ assert(full_backing);
124
125
/* backing files always opened read-only */
126
back_flags = flags;
127
diff --git a/block/vmdk.c b/block/vmdk.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/block/vmdk.c
130
+++ b/block/vmdk.c
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
132
133
if (backing_file) {
134
BlockBackend *backing;
135
- char *full_backing = g_new0(char, PATH_MAX);
136
- bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
137
- full_backing, PATH_MAX,
138
- &local_err);
139
+ char *full_backing =
140
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename,
141
+ backing_file,
142
+ &local_err);
143
if (local_err) {
144
- g_free(full_backing);
145
error_propagate(errp, local_err);
146
ret = -ENOENT;
147
goto exit;
148
}
149
+ assert(full_backing);
150
151
backing = blk_new_open(full_backing, NULL, NULL,
152
BDRV_O_NO_BACKING, errp);
153
diff --git a/qemu-img.c b/qemu-img.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/qemu-img.c
156
+++ b/qemu-img.c
157
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
158
bdrv_refresh_filename(bs);
159
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
160
: bs->filename;
161
- out_real_path = g_malloc(PATH_MAX);
162
-
163
- bdrv_get_full_backing_filename_from_filename(overlay_filename,
164
- out_baseimg,
165
- out_real_path,
166
- PATH_MAX,
167
- &local_err);
168
+ out_real_path =
169
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
170
+ out_baseimg,
171
+ &local_err);
172
if (local_err) {
173
error_reportf_err(local_err,
174
"Could not resolve backing filename: ");
175
ret = -1;
176
- g_free(out_real_path);
177
goto out;
178
}
179
180
--
132
--
181
2.20.1
133
2.37.3
182
183
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Instead of having every block driver which implements
3
child_job_change_aio_ctx() is very similar to
4
bdrv_refresh_filename() copy all of the strong runtime options over to
4
child_job_can_set_aio_ctx(), but it implements a new transaction
5
bs->full_open_options, implement this process generically in
5
so that if all check pass, the new transaction's .commit()
6
bdrv_refresh_filename().
6
will take care of changin the BlockJob AioContext.
7
child_job_set_aio_ctx_commit() is similar to child_job_set_aio_ctx(),
8
but it doesn't need to invoke the recursion, as this is already
9
taken care by child_job_change_aio_ctx().
7
10
8
This patch only adds this new generic implementation, it does not remove
11
Note: bdrv_child_try_change_aio_context() is not called by
9
the old functionality. This is done in a follow-up patch.
12
anyone at this point.
10
13
11
With this patch, some superfluous information (that should never have
14
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
been there) may be removed from some JSON filenames, as can be seen in
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
the change to iotests 110's and 228's reference outputs.
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20221025084952.2139888-5-eesposit@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
blockjob.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
21
1 file changed, 45 insertions(+)
14
22
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
diff --git a/blockjob.c b/blockjob.c
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
24
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
25
--- a/blockjob.c
28
+++ b/block.c
26
+++ b/blockjob.c
29
@@ -XXX,XX +XXX,XX @@ out:
27
@@ -XXX,XX +XXX,XX @@ static void child_job_drained_end(BdrvChild *c, int *drained_end_counter)
30
return to_replace_bs;
28
job_resume(&job->job);
31
}
29
}
32
30
33
+/**
31
+typedef struct BdrvStateChildJobContext {
34
+ * Iterates through the list of runtime option keys that are said to
32
+ AioContext *new_ctx;
35
+ * be "strong" for a BDS. An option is called "strong" if it changes
33
+ BlockJob *job;
36
+ * a BDS's data. For example, the null block driver's "size" and
34
+} BdrvStateChildJobContext;
37
+ * "read-zeroes" options are strong, but its "latency-ns" option is
35
+
38
+ * not.
36
+static void child_job_set_aio_ctx_commit(void *opaque)
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
+{
37
+{
46
+ static const char *const global_options[] = {
38
+ BdrvStateChildJobContext *s = opaque;
47
+ "driver", "filename", NULL
39
+ BlockJob *job = s->job;
48
+ };
49
+
40
+
50
+ if (!curopt) {
41
+ job_set_aio_context(&job->job, s->new_ctx);
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
+}
42
+}
61
+
43
+
62
+/**
44
+static TransactionActionDrv change_child_job_context = {
63
+ * Copies all strong runtime options from bs->options to the given
45
+ .commit = child_job_set_aio_ctx_commit,
64
+ * QDict. The set of strong option keys is determined by invoking
46
+ .clean = g_free,
65
+ * strong_options().
47
+};
66
+ *
48
+
67
+ * Returns true iff any strong option was present in bs->options (and
49
+static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
68
+ * thus copied to the target QDict) with the exception of "filename"
50
+ GHashTable *visited, Transaction *tran,
69
+ * and "driver". The caller is expected to use this value to decide
51
+ Error **errp)
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
+{
52
+{
75
+ bool found_any = false;
53
+ BlockJob *job = c->opaque;
76
+ const char *const *option_name = NULL;
54
+ BdrvStateChildJobContext *s;
55
+ GSList *l;
77
+
56
+
78
+ if (!bs->drv) {
57
+ for (l = job->nodes; l; l = l->next) {
79
+ return false;
58
+ BdrvChild *sibling = l->data;
80
+ }
59
+ if (!bdrv_child_change_aio_context(sibling, ctx, visited,
81
+
60
+ tran, errp)) {
82
+ while ((option_name = strong_options(bs, option_name))) {
61
+ return false;
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
+ }
62
+ }
114
+ }
63
+ }
115
+
64
+
116
+ return found_any;
65
+ s = g_new(BdrvStateChildJobContext, 1);
66
+ *s = (BdrvStateChildJobContext) {
67
+ .new_ctx = ctx,
68
+ .job = job,
69
+ };
70
+
71
+ tran_add(tran, &change_child_job_context, s);
72
+ return true;
117
+}
73
+}
118
+
74
+
119
static bool append_open_options(QDict *d, BlockDriverState *bs)
75
static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
76
GSList **ignore, Error **errp)
120
{
77
{
121
const QDictEntry *entry;
78
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
122
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
79
.drained_end = child_job_drained_end,
123
bs->full_open_options = opts;
80
.can_set_aio_ctx = child_job_can_set_aio_ctx,
124
}
81
.set_aio_ctx = child_job_set_aio_ctx,
125
82
+ .change_aio_ctx = child_job_change_aio_ctx,
126
+ /* Gather the options QDict */
83
.stay_at_node = true,
127
+ opts = qdict_new();
84
.get_parent_aio_context = child_job_get_parent_aio_context,
128
+ append_strong_runtime_options(opts, bs);
85
};
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
--
86
--
206
2.20.1
87
2.37.3
207
208
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This is a general function for making a filename that is relative to a
3
bdrv_child_cb_change_aio_ctx() is identical to
4
certain BDS absolute.
4
bdrv_child_cb_can_set_aio_ctx(), as we only need
5
to recursively go on the parent bs.
5
6
6
It calls bdrv_get_full_backing_filename_from_filename() for now, but
7
Note: bdrv_child_try_change_aio_context() is not called by
7
that will be changed in a follow-up patch.
8
anyone at this point.
8
9
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20190201192935.18394-13-mreitz@redhat.com
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20221025084952.2139888-6-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
15
---
14
block.c | 27 ++++++++++++++++++++-------
16
block.c | 9 +++++++++
15
1 file changed, 20 insertions(+), 7 deletions(-)
17
1 file changed, 9 insertions(+)
16
18
17
diff --git a/block.c b/block.c
19
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
21
--- a/block.c
20
+++ b/block.c
22
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
23
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_cb_inactivate(BdrvChild *child)
22
}
24
return 0;
23
}
25
}
24
26
25
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
27
+static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
26
+/*
28
+ GHashTable *visited, Transaction *tran,
27
+ * If @filename is empty or NULL, this function returns NULL without
29
+ Error **errp)
28
+ * setting @errp. In all other cases, NULL will only be returned with
30
+{
29
+ * @errp set.
31
+ BlockDriverState *bs = child->opaque;
30
+ */
32
+ return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
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
+}
33
+}
51
+
34
+
52
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
35
static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
53
+{
36
GSList **ignore, Error **errp)
54
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
37
{
55
}
38
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
56
39
.inactivate = bdrv_child_cb_inactivate,
57
void bdrv_register(BlockDriver *bdrv)
40
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
41
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
42
+ .change_aio_ctx = bdrv_child_cb_change_aio_ctx,
43
.update_filename = bdrv_child_cb_update_filename,
44
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
45
};
58
--
46
--
59
2.20.1
47
2.37.3
60
61
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
The previous patch includes the LUKS payload overhead into the qemu-img
3
blk_root_change_aio_ctx() is very similar to blk_root_can_set_aio_ctx(),
4
measure calculation for qcow2. Update qemu-iotests 178 to exercise this
4
but implements a new transaction so that if all check pass, the new
5
new code path.
5
transaction's .commit will take care of changing the BlockBackend
6
AioContext. blk_root_set_aio_ctx_commit() is the same as
7
blk_root_set_aio_ctx().
6
8
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Note: bdrv_child_try_change_aio_context() is not called by
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
anyone at this point.
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
10
Message-id: 20190218104525.23674-3-stefanha@redhat.com
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20221025084952.2139888-7-eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
16
---
13
tests/qemu-iotests/178 | 8 ++++++++
17
block/block-backend.c | 52 +++++++++++++++++++++++++++++++++++++++++++
14
tests/qemu-iotests/178.out.qcow2 | 24 ++++++++++++++++++++++++
18
1 file changed, 52 insertions(+)
15
2 files changed, 32 insertions(+)
16
19
17
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
20
diff --git a/block/block-backend.c b/block/block-backend.c
18
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/178
22
--- a/block/block-backend.c
20
+++ b/tests/qemu-iotests/178
23
+++ b/block/block-backend.c
21
@@ -XXX,XX +XXX,XX @@ for ofmt in human json; do
24
@@ -XXX,XX +XXX,XX @@ static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
22
# The backing file doesn't need to exist :)
25
GSList **ignore, Error **errp);
23
$QEMU_IMG measure --output=$ofmt -o backing_file=x \
26
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
24
-f "$fmt" -O "$IMGFMT" "$TEST_IMG"
27
GSList **ignore);
28
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
29
+ GHashTable *visited, Transaction *tran,
30
+ Error **errp);
31
32
static char *blk_root_get_parent_desc(BdrvChild *child)
33
{
34
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
35
36
.can_set_aio_ctx = blk_root_can_set_aio_ctx,
37
.set_aio_ctx = blk_root_set_aio_ctx,
38
+ .change_aio_ctx = blk_root_change_aio_ctx,
39
40
.get_parent_aio_context = blk_root_get_parent_aio_context,
41
};
42
@@ -XXX,XX +XXX,XX @@ int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
43
return blk_do_set_aio_context(blk, new_context, true, errp);
44
}
45
46
+typedef struct BdrvStateBlkRootContext {
47
+ AioContext *new_ctx;
48
+ BlockBackend *blk;
49
+} BdrvStateBlkRootContext;
25
+
50
+
26
+ echo
51
+static void blk_root_set_aio_ctx_commit(void *opaque)
27
+ echo "== $fmt input image and LUKS encryption =="
52
+{
28
+ echo
53
+ BdrvStateBlkRootContext *s = opaque;
29
+ $QEMU_IMG measure --output=$ofmt \
54
+ BlockBackend *blk = s->blk;
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
+
55
+
46
+required size: 2686976
56
+ blk_do_set_aio_context(blk, s->new_ctx, false, &error_abort);
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
+}
57
+}
74
+
58
+
75
== qcow2 input image and preallocation (json) ==
59
+static TransactionActionDrv set_blk_root_context = {
76
60
+ .commit = blk_root_set_aio_ctx_commit,
77
{
61
+ .clean = g_free,
78
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 524288
62
+};
79
"fully-allocated": 1074135040
80
}
81
82
+== raw input image and LUKS encryption ==
83
+
63
+
64
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
65
+ GHashTable *visited, Transaction *tran,
66
+ Error **errp)
84
+{
67
+{
85
+ "required": 2686976,
68
+ BlockBackend *blk = child->opaque;
86
+ "fully-allocated": 1076232192
69
+ BdrvStateBlkRootContext *s;
70
+
71
+ if (!blk->allow_aio_context_change) {
72
+ /*
73
+ * Manually created BlockBackends (those with a name) that are not
74
+ * attached to anything can change their AioContext without updating
75
+ * their user; return an error for others.
76
+ */
77
+ if (!blk->name || blk->dev) {
78
+ /* TODO Add BB name/QOM path */
79
+ error_setg(errp, "Cannot change iothread of active block backend");
80
+ return false;
81
+ }
82
+ }
83
+
84
+ s = g_new(BdrvStateBlkRootContext, 1);
85
+ *s = (BdrvStateBlkRootContext) {
86
+ .new_ctx = ctx,
87
+ .blk = blk,
88
+ };
89
+
90
+ tran_add(tran, &set_blk_root_context, s);
91
+ return true;
87
+}
92
+}
88
+
93
+
89
== raw input image and preallocation (json) ==
94
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
90
95
GSList **ignore, Error **errp)
91
{
96
{
92
--
97
--
93
2.20.1
98
2.37.3
94
95
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
bdrv_get_full_backing_filename_from_filename() breaks down when it comes
3
Replace all direct usage of ->can_set_aio_ctx and ->set_aio_ctx,
4
to JSON filenames. Using bdrv_dirname() as the basis is better because
4
and call bdrv_child_try_change_aio_context() in
5
since we have BDS, we can descend through the BDS tree to the protocol
5
bdrv_try_set_aio_context(), the main function called through
6
layer, which gives us a greater probability of finding a non-JSON name;
6
the whole block layer.
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
7
11
We still need to keep bdrv_get_full_backing_filename_from_filename(),
8
From this point onwards, ->can_set_aio_ctx and ->set_aio_ctx
12
though, because it has valid callers which need it during image creation
9
won't be used anymore.
13
when no BDS is available yet.
14
10
15
This makes a test case in qemu-iotest 110, which was supposed to fail,
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
16
work. That is actually good, but we need to change the reference output
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
(and the comment in 110) accordingly.
13
Message-Id: <20221025084952.2139888-8-eesposit@redhat.com>
18
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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
---
15
---
24
block.c | 20 +++++++++++++-------
16
block.c | 44 ++++++++++++++++++++++++-------------------
25
tests/qemu-iotests/110 | 3 ++-
17
block/block-backend.c | 8 ++++++--
26
tests/qemu-iotests/110.out | 2 +-
18
2 files changed, 31 insertions(+), 21 deletions(-)
27
3 files changed, 16 insertions(+), 9 deletions(-)
28
19
29
diff --git a/block.c b/block.c
20
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
22
--- a/block.c
32
+++ b/block.c
23
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
24
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
34
static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
25
}
35
const char *filename, Error **errp)
26
27
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
28
- GSList *ignore;
29
+ Transaction *tran;
30
+ GHashTable *visited;
31
+ bool ret;
32
33
- /* No need to ignore `child`, because it has been detached already */
34
- ignore = NULL;
35
- s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
36
- &error_abort);
37
- g_slist_free(ignore);
38
+ tran = tran_new();
39
40
- ignore = NULL;
41
- s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
42
- g_slist_free(ignore);
43
+ /* No need to visit `child`, because it has been detached already */
44
+ visited = g_hash_table_new(NULL, NULL);
45
+ ret = s->child->klass->change_aio_ctx(s->child, s->old_parent_ctx,
46
+ visited, tran, &error_abort);
47
+ g_hash_table_destroy(visited);
48
+
49
+ /* transaction is supposed to always succeed */
50
+ assert(ret == true);
51
+ tran_commit(tran);
52
}
53
54
bdrv_unref(bs);
55
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
56
Error *local_err = NULL;
57
int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
58
59
- if (ret < 0 && child_class->can_set_aio_ctx) {
60
- GSList *ignore = g_slist_prepend(NULL, new_child);
61
- if (child_class->can_set_aio_ctx(new_child, child_ctx, &ignore,
62
- NULL))
63
- {
64
+ if (ret < 0 && child_class->change_aio_ctx) {
65
+ Transaction *tran = tran_new();
66
+ GHashTable *visited = g_hash_table_new(NULL, NULL);
67
+ bool ret_child;
68
+
69
+ g_hash_table_add(visited, new_child);
70
+ ret_child = child_class->change_aio_ctx(new_child, child_ctx,
71
+ visited, tran, NULL);
72
+ if (ret_child == true) {
73
error_free(local_err);
74
ret = 0;
75
- g_slist_free(ignore);
76
- ignore = g_slist_prepend(NULL, new_child);
77
- child_class->set_aio_ctx(new_child, child_ctx, &ignore);
78
}
79
- g_slist_free(ignore);
80
+ tran_finalize(tran, ret_child == true ? 0 : -1);
81
+ g_hash_table_destroy(visited);
82
}
83
84
if (ret < 0) {
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
86
Error **errp)
36
{
87
{
37
- char *bs_filename;
88
GLOBAL_STATE_CODE();
38
+ char *dir, *full_name;
89
- return bdrv_child_try_set_aio_context(bs, ctx, NULL, errp);
39
90
+ return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
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
}
91
}
61
92
62
char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
93
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
63
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
94
diff --git a/block/block-backend.c b/block/block-backend.c
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
95
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/110.out
96
--- a/block/block-backend.c
80
+++ b/tests/qemu-iotests/110.out
97
+++ b/block/block-backend.c
81
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
98
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
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}}
99
bdrv_ref(bs);
83
file format: IMGFMT
100
84
virtual size: 64M (67108864 bytes)
101
if (update_root_node) {
85
-backing file: t.IMGFMT.base (cannot determine actual path)
102
- ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
86
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
103
- errp);
87
104
+ /*
88
=== Backing name is always relative to the backed image ===
105
+ * update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
89
106
+ * as we are already in the commit function of a transaction.
107
+ */
108
+ ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
109
+ errp);
110
if (ret < 0) {
111
bdrv_unref(bs);
112
return ret;
90
--
113
--
91
2.20.1
114
2.37.3
92
93
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
bdrv_find_backing_image() should use bdrv_get_full_backing_filename() or
3
Together with all _can_set_ and _set_ APIs, as they are not needed
4
bdrv_make_absolute_filename() instead of trying to do what those
4
anymore.
5
functions do by itself.
6
5
7
path_combine_deprecated() can now be dropped, so let's do that.
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20221025084952.2139888-9-eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 9 --
12
include/block/block_int-common.h | 4 -
13
block.c | 196 -----------------------------
14
block/block-backend.c | 33 -----
15
blockjob.c | 35 ------
16
5 files changed, 277 deletions(-)
8
17
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
19
index XXXXXXX..XXXXXXX 100644
11
Message-id: 20190201192935.18394-14-mreitz@redhat.com
20
--- a/include/block/block-global-state.h
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
+++ b/include/block/block-global-state.h
13
---
22
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
14
block.c | 33 ++++++++++-----------------------
23
*/
15
1 file changed, 10 insertions(+), 23 deletions(-)
24
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
16
25
26
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
27
- AioContext *new_context, GSList **ignore);
28
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
29
Error **errp);
30
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
31
- BdrvChild *ignore_child, Error **errp);
32
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
33
- GSList **ignore, Error **errp);
34
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
35
- GSList **ignore, Error **errp);
36
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
37
-
38
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
39
GHashTable *visited, Transaction *tran,
40
Error **errp);
41
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block_int-common.h
44
+++ b/include/block/block_int-common.h
45
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
46
int (*update_filename)(BdrvChild *child, BlockDriverState *new_base,
47
const char *filename, Error **errp);
48
49
- bool (*can_set_aio_ctx)(BdrvChild *child, AioContext *ctx,
50
- GSList **ignore, Error **errp);
51
- void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
52
-
53
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
54
GHashTable *visited, Transaction *tran,
55
Error **errp);
17
diff --git a/block.c b/block.c
56
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
58
--- a/block.c
20
+++ b/block.c
59
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *path_combine(const char *base_path, const char *filename)
60
@@ -XXX,XX +XXX,XX @@ static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
22
return result;
61
return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
23
}
62
}
24
63
25
-static void path_combine_deprecated(char *dest, int dest_size,
64
-static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
26
- const char *base_path,
65
- GSList **ignore, Error **errp)
27
- const char *filename)
66
-{
28
-{
67
- BlockDriverState *bs = child->opaque;
29
- char *combined = path_combine(base_path, filename);
68
- return bdrv_can_set_aio_context(bs, ctx, ignore, errp);
30
- pstrcpy(dest, dest_size, combined);
69
-}
31
- g_free(combined);
70
-
71
-static void bdrv_child_cb_set_aio_ctx(BdrvChild *child, AioContext *ctx,
72
- GSList **ignore)
73
-{
74
- BlockDriverState *bs = child->opaque;
75
- return bdrv_set_aio_context_ignore(bs, ctx, ignore);
32
-}
76
-}
33
-
77
-
34
/*
78
/*
35
* Helper function for bdrv_parse_filename() implementations to remove optional
79
* Returns the options and flags that a temporary snapshot should get, based on
36
* protocol prefixes (especially "file:") from a filename and for putting the
80
* the originally requested flags (the originally requested image will have
37
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
81
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
38
82
.attach = bdrv_child_cb_attach,
39
filename_full = g_malloc(PATH_MAX);
83
.detach = bdrv_child_cb_detach,
40
backing_file_full = g_malloc(PATH_MAX);
84
.inactivate = bdrv_child_cb_inactivate,
41
- filename_tmp = g_malloc(PATH_MAX);
85
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
42
86
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
43
is_protocol = path_has_protocol(backing_file);
87
.change_aio_ctx = bdrv_child_cb_change_aio_ctx,
44
88
.update_filename = bdrv_child_cb_update_filename,
45
- /* This will recursively refresh everything in the backing chain */
89
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
46
- bdrv_refresh_filename(bs);
90
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
47
-
91
bs->walking_aio_notifiers = false;
48
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
92
}
49
93
50
/* If either of the filename paths is actually a protocol, then
94
-/*
51
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
95
- * Changes the AioContext used for fd handlers, timers, and BHs by this
52
} else {
96
- * BlockDriverState and all its children and parents.
53
/* If not an absolute filename path, make it relative to the current
97
- *
54
* image's filename path */
98
- * Must be called from the main AioContext.
55
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
99
- *
56
- backing_file);
100
- * The caller must own the AioContext lock for the old AioContext of bs, but it
57
-
101
- * must not own the AioContext lock for new_context (unless new_context is the
58
- /* We are going to compare absolute pathnames */
102
- * same as the current context of bs).
59
- if (!realpath(filename_tmp, filename_full)) {
103
- *
60
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
104
- * @ignore will accumulate all visited BdrvChild objects. The caller is
61
+ NULL);
105
- * responsible for freeing the list afterwards.
62
+ /* We are going to compare canonicalized absolute pathnames */
106
- */
63
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
107
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
64
+ g_free(filename_tmp);
108
- AioContext *new_context, GSList **ignore)
65
continue;
109
-{
66
}
110
- AioContext *old_context = bdrv_get_aio_context(bs);
67
+ g_free(filename_tmp);
111
- GSList *children_to_process = NULL;
68
112
- GSList *parents_to_process = NULL;
69
/* We need to make sure the backing filename we are comparing against
113
- GSList *entry;
70
* is relative to the current image filename (or absolute) */
114
- BdrvChild *child, *parent;
71
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
115
-
72
- curr_bs->backing_file);
116
- g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
73
-
117
- GLOBAL_STATE_CODE();
74
- if (!realpath(filename_tmp, backing_file_full)) {
118
-
75
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
119
- if (old_context == new_context) {
76
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
120
- return;
77
+ g_free(filename_tmp);
121
- }
78
continue;
122
-
79
}
123
- bdrv_drained_begin(bs);
80
+ g_free(filename_tmp);
124
-
81
125
- QLIST_FOREACH(child, &bs->children, next) {
82
if (strcmp(backing_file_full, filename_full) == 0) {
126
- if (g_slist_find(*ignore, child)) {
83
retval = curr_bs->backing->bs;
127
- continue;
84
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
128
- }
85
129
- *ignore = g_slist_prepend(*ignore, child);
86
g_free(filename_full);
130
- children_to_process = g_slist_prepend(children_to_process, child);
87
g_free(backing_file_full);
131
- }
88
- g_free(filename_tmp);
132
-
89
return retval;
133
- QLIST_FOREACH(parent, &bs->parents, next_parent) {
90
}
134
- if (g_slist_find(*ignore, parent)) {
91
135
- continue;
136
- }
137
- *ignore = g_slist_prepend(*ignore, parent);
138
- parents_to_process = g_slist_prepend(parents_to_process, parent);
139
- }
140
-
141
- for (entry = children_to_process;
142
- entry != NULL;
143
- entry = g_slist_next(entry)) {
144
- child = entry->data;
145
- bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
146
- }
147
- g_slist_free(children_to_process);
148
-
149
- for (entry = parents_to_process;
150
- entry != NULL;
151
- entry = g_slist_next(entry)) {
152
- parent = entry->data;
153
- assert(parent->klass->set_aio_ctx);
154
- parent->klass->set_aio_ctx(parent, new_context, ignore);
155
- }
156
- g_slist_free(parents_to_process);
157
-
158
- bdrv_detach_aio_context(bs);
159
-
160
- /* Acquire the new context, if necessary */
161
- if (qemu_get_aio_context() != new_context) {
162
- aio_context_acquire(new_context);
163
- }
164
-
165
- bdrv_attach_aio_context(bs, new_context);
166
-
167
- /*
168
- * If this function was recursively called from
169
- * bdrv_set_aio_context_ignore(), there may be nodes in the
170
- * subtree that have not yet been moved to the new AioContext.
171
- * Release the old one so bdrv_drained_end() can poll them.
172
- */
173
- if (qemu_get_aio_context() != old_context) {
174
- aio_context_release(old_context);
175
- }
176
-
177
- bdrv_drained_end(bs);
178
-
179
- if (qemu_get_aio_context() != old_context) {
180
- aio_context_acquire(old_context);
181
- }
182
- if (qemu_get_aio_context() != new_context) {
183
- aio_context_release(new_context);
184
- }
185
-}
186
-
187
-static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
188
- GSList **ignore, Error **errp)
189
-{
190
- GLOBAL_STATE_CODE();
191
- if (g_slist_find(*ignore, c)) {
192
- return true;
193
- }
194
- *ignore = g_slist_prepend(*ignore, c);
195
-
196
- /*
197
- * A BdrvChildClass that doesn't handle AioContext changes cannot
198
- * tolerate any AioContext changes
199
- */
200
- if (!c->klass->can_set_aio_ctx) {
201
- char *user = bdrv_child_user_desc(c);
202
- error_setg(errp, "Changing iothreads is not supported by %s", user);
203
- g_free(user);
204
- return false;
205
- }
206
- if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
207
- assert(!errp || *errp);
208
- return false;
209
- }
210
- return true;
211
-}
212
-
213
typedef struct BdrvStateSetAioContext {
214
AioContext *new_ctx;
215
BlockDriverState *bs;
216
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
217
return true;
218
}
219
220
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
221
- GSList **ignore, Error **errp)
222
-{
223
- GLOBAL_STATE_CODE();
224
- if (g_slist_find(*ignore, c)) {
225
- return true;
226
- }
227
- *ignore = g_slist_prepend(*ignore, c);
228
- return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
229
-}
230
-
231
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
232
GHashTable *visited, Transaction *tran,
233
Error **errp)
234
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
235
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
236
}
237
238
-/* @ignore will accumulate all visited BdrvChild object. The caller is
239
- * responsible for freeing the list afterwards. */
240
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
241
- GSList **ignore, Error **errp)
242
-{
243
- BdrvChild *c;
244
-
245
- if (bdrv_get_aio_context(bs) == ctx) {
246
- return true;
247
- }
248
-
249
- GLOBAL_STATE_CODE();
250
-
251
- QLIST_FOREACH(c, &bs->parents, next_parent) {
252
- if (!bdrv_parent_can_set_aio_context(c, ctx, ignore, errp)) {
253
- return false;
254
- }
255
- }
256
- QLIST_FOREACH(c, &bs->children, next) {
257
- if (!bdrv_child_can_set_aio_context(c, ctx, ignore, errp)) {
258
- return false;
259
- }
260
- }
261
-
262
- return true;
263
-}
264
-
265
static void bdrv_set_aio_context_clean(void *opaque)
266
{
267
BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
268
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
269
return true;
270
}
271
272
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
273
- BdrvChild *ignore_child, Error **errp)
274
-{
275
- GSList *ignore;
276
- bool ret;
277
-
278
- GLOBAL_STATE_CODE();
279
-
280
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
281
- ret = bdrv_can_set_aio_context(bs, ctx, &ignore, errp);
282
- g_slist_free(ignore);
283
-
284
- if (!ret) {
285
- return -EPERM;
286
- }
287
-
288
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
289
- bdrv_set_aio_context_ignore(bs, ctx, &ignore);
290
- g_slist_free(ignore);
291
-
292
- return 0;
293
-}
294
-
295
/*
296
* Change bs's and recursively all of its parents' and children's AioContext
297
* to the given new context, returning an error if that isn't possible.
298
diff --git a/block/block-backend.c b/block/block-backend.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/block/block-backend.c
301
+++ b/block/block-backend.c
302
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter);
303
static void blk_root_change_media(BdrvChild *child, bool load);
304
static void blk_root_resize(BdrvChild *child);
305
306
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
307
- GSList **ignore, Error **errp);
308
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
309
- GSList **ignore);
310
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
311
GHashTable *visited, Transaction *tran,
312
Error **errp);
313
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
314
.attach = blk_root_attach,
315
.detach = blk_root_detach,
316
317
- .can_set_aio_ctx = blk_root_can_set_aio_ctx,
318
- .set_aio_ctx = blk_root_set_aio_ctx,
319
.change_aio_ctx = blk_root_change_aio_ctx,
320
321
.get_parent_aio_context = blk_root_get_parent_aio_context,
322
@@ -XXX,XX +XXX,XX @@ static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
323
return true;
324
}
325
326
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
327
- GSList **ignore, Error **errp)
328
-{
329
- BlockBackend *blk = child->opaque;
330
-
331
- if (blk->allow_aio_context_change) {
332
- return true;
333
- }
334
-
335
- /* Only manually created BlockBackends that are not attached to anything
336
- * can change their AioContext without updating their user. */
337
- if (!blk->name || blk->dev) {
338
- /* TODO Add BB name/QOM path */
339
- error_setg(errp, "Cannot change iothread of active block backend");
340
- return false;
341
- }
342
-
343
- return true;
344
-}
345
-
346
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
347
- GSList **ignore)
348
-{
349
- BlockBackend *blk = child->opaque;
350
- blk_do_set_aio_context(blk, ctx, false, &error_abort);
351
-}
352
-
353
void blk_add_aio_context_notifier(BlockBackend *blk,
354
void (*attached_aio_context)(AioContext *new_context, void *opaque),
355
void (*detach_aio_context)(void *opaque), void *opaque)
356
diff --git a/blockjob.c b/blockjob.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/blockjob.c
359
+++ b/blockjob.c
360
@@ -XXX,XX +XXX,XX @@ static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
361
return true;
362
}
363
364
-static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
365
- GSList **ignore, Error **errp)
366
-{
367
- BlockJob *job = c->opaque;
368
- GSList *l;
369
-
370
- for (l = job->nodes; l; l = l->next) {
371
- BdrvChild *sibling = l->data;
372
- if (!bdrv_child_can_set_aio_context(sibling, ctx, ignore, errp)) {
373
- return false;
374
- }
375
- }
376
- return true;
377
-}
378
-
379
-static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
380
- GSList **ignore)
381
-{
382
- BlockJob *job = c->opaque;
383
- GSList *l;
384
-
385
- for (l = job->nodes; l; l = l->next) {
386
- BdrvChild *sibling = l->data;
387
- if (g_slist_find(*ignore, sibling)) {
388
- continue;
389
- }
390
- *ignore = g_slist_prepend(*ignore, sibling);
391
- bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
392
- }
393
-
394
- job_set_aio_context(&job->job, ctx);
395
-}
396
-
397
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
398
{
399
BlockJob *job = c->opaque;
400
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
401
.drained_begin = child_job_drained_begin,
402
.drained_poll = child_job_drained_poll,
403
.drained_end = child_job_drained_end,
404
- .can_set_aio_ctx = child_job_can_set_aio_ctx,
405
- .set_aio_ctx = child_job_set_aio_ctx,
406
.change_aio_ctx = child_job_change_aio_ctx,
407
.stay_at_node = true,
408
.get_parent_aio_context = child_job_get_parent_aio_context,
92
--
409
--
93
2.20.1
410
2.37.3
94
95
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
This function may be implemented by block drivers to derive a directory
3
No functional changes intended.
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
4
9
If a BDS's driver does not implement this function, bdrv_dirname() will
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
fall through to the BDS's file if it exists. If it does not, the
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
exact_filename field will be used to generate a directory name.
7
Message-Id: <20221025084952.2139888-10-eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-global-state.h | 4 ++--
11
block.c | 6 +++---
12
block/block-backend.c | 3 +--
13
3 files changed, 6 insertions(+), 7 deletions(-)
12
14
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
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
16
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block.h
17
--- a/include/block/block-global-state.h
26
+++ b/include/block/block.h
18
+++ b/include/block/block-global-state.h
27
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
19
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
28
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
20
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
29
const char *backing,
21
GHashTable *visited, Transaction *tran,
30
Error **errp);
22
Error **errp);
31
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
23
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
32
24
- BdrvChild *ignore_child, Error **errp);
33
int path_has_protocol(const char *path);
25
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
34
int path_is_absolute(const char *path);
26
+ BdrvChild *ignore_child, Error **errp);
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
27
36
index XXXXXXX..XXXXXXX 100644
28
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
37
--- a/include/block/block_int.h
29
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
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
30
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
32
--- a/block.c
56
+++ b/block.c
33
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
34
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
58
}
35
* bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
36
* Therefore the new AioContext lock must not be taken by the caller.
37
*/
38
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
39
- BdrvChild *ignore_child, Error **errp)
40
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
41
+ BdrvChild *ignore_child, Error **errp)
42
{
43
Transaction *tran;
44
GHashTable *visited;
45
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
46
Error **errp)
47
{
48
GLOBAL_STATE_CODE();
49
- return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
50
+ return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
59
}
51
}
60
52
61
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
53
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
62
+{
54
diff --git a/block/block-backend.c b/block/block-backend.c
63
+ BlockDriver *drv = bs->drv;
55
index XXXXXXX..XXXXXXX 100644
64
+
56
--- a/block/block-backend.c
65
+ if (!drv) {
57
+++ b/block/block-backend.c
66
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
58
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
67
+ return NULL;
59
* update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
68
+ }
60
* as we are already in the commit function of a transaction.
69
+
61
*/
70
+ if (drv->bdrv_dirname) {
62
- ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
71
+ return drv->bdrv_dirname(bs, errp);
63
- errp);
72
+ }
64
+ ret = bdrv_try_change_aio_context(bs, new_context, blk->root, errp);
73
+
65
if (ret < 0) {
74
+ if (bs->file) {
66
bdrv_unref(bs);
75
+ return bdrv_dirname(bs->file->bs, errp);
67
return ret;
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
--
68
--
92
2.20.1
69
2.37.3
93
94
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Make bdrv_get_full_backing_filename() return an allocated string instead
3
No functional change intended.
4
of placing the result in a caller-provided buffer.
5
4
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Message-id: 20190201192935.18394-12-mreitz@redhat.com
7
Message-Id: <20221025084952.2139888-11-eesposit@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
include/block/block.h | 3 +--
10
docs/devel/multiple-iothreads.txt | 4 ++--
12
block.c | 48 +++++++++++++++----------------------------
11
include/block/block-global-state.h | 2 --
13
block/qapi.c | 12 ++---------
12
block.c | 14 ++++----------
14
3 files changed, 20 insertions(+), 43 deletions(-)
13
block/export/export.c | 2 +-
14
blockdev.c | 22 +++++++++++-----------
15
job.c | 2 +-
16
tests/unit/test-bdrv-drain.c | 6 +++---
17
tests/unit/test-block-iothread.c | 10 +++++-----
18
8 files changed, 27 insertions(+), 35 deletions(-)
15
19
16
diff --git a/include/block/block.h b/include/block/block.h
20
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
22
--- a/docs/devel/multiple-iothreads.txt
19
+++ b/include/block/block.h
23
+++ b/docs/devel/multiple-iothreads.txt
20
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
24
@@ -XXX,XX +XXX,XX @@ The AioContext originates from the QEMU block layer, even though nowadays
21
25
AioContext is a generic event loop that can be used by any QEMU subsystem.
22
void bdrv_get_backing_filename(BlockDriverState *bs,
26
23
char *filename, int filename_size);
27
The block layer has support for AioContext integrated. Each BlockDriverState
24
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
28
-is associated with an AioContext using bdrv_try_set_aio_context() and
25
- char *dest, size_t sz, Error **errp);
29
+is associated with an AioContext using bdrv_try_change_aio_context() and
26
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
30
bdrv_get_aio_context(). This allows block layer code to process I/O inside the
27
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
31
right AioContext. Other subsystems may wish to follow a similar approach.
28
const char *backing,
32
29
Error **errp);
33
@@ -XXX,XX +XXX,XX @@ Long-running jobs (usually in the form of coroutines) are best scheduled in
34
the BlockDriverState's AioContext to avoid the need to acquire/release around
35
each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
36
or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
37
-can be used to get a notification whenever bdrv_try_set_aio_context() moves a
38
+can be used to get a notification whenever bdrv_try_change_aio_context() moves a
39
BlockDriverState to a different AioContext.
40
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block-global-state.h
43
+++ b/include/block/block-global-state.h
44
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
45
*/
46
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
47
48
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
49
- Error **errp);
50
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
51
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
52
GHashTable *visited, Transaction *tran,
30
diff --git a/block.c b/block.c
53
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
55
--- a/block.c
33
+++ b/block.c
56
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
57
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
58
bdrv_replace_child_noperm(s->child, NULL);
59
60
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
61
- bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
62
+ bdrv_try_change_aio_context(bs, s->old_child_ctx, NULL, &error_abort);
63
}
64
65
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
66
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
67
parent_ctx = bdrv_child_get_parent_aio_context(new_child);
68
if (child_ctx != parent_ctx) {
69
Error *local_err = NULL;
70
- int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
71
+ int ret = bdrv_try_change_aio_context(child_bs, parent_ctx, NULL,
72
+ &local_err);
73
74
if (ret < 0 && child_class->change_aio_ctx) {
75
Transaction *tran = tran_new();
76
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild *child)
77
* When the parent requiring a non-default AioContext is removed, the
78
* node moves back to the main AioContext
79
*/
80
- bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
81
+ bdrv_try_change_aio_context(old_bs, qemu_get_aio_context(), NULL, NULL);
35
}
82
}
36
}
83
}
37
84
38
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
39
- Error **errp)
86
return 0;
40
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
87
}
41
{
88
42
char *backed;
89
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
43
- char *full_name;
90
- Error **errp)
44
- Error *local_error = NULL;
91
-{
45
92
- GLOBAL_STATE_CODE();
46
bdrv_refresh_filename(bs);
93
- return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
47
94
-}
48
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
49
-
95
-
50
- full_name = bdrv_get_full_backing_filename_from_filename(backed,
96
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
51
- bs->backing_file,
97
void (*attached_aio_context)(AioContext *new_context, void *opaque),
52
- &local_error);
98
void (*detach_aio_context)(void *opaque), void *opaque)
53
- if (full_name) {
99
diff --git a/block/export/export.c b/block/export/export.c
54
- pstrcpy(dest, sz, full_name);
100
index XXXXXXX..XXXXXXX 100644
55
- g_free(full_name);
101
--- a/block/export/export.c
56
- } else if (local_error) {
102
+++ b/block/export/export.c
57
- error_propagate(errp, local_error);
103
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
58
- } else if (sz > 0) {
104
59
- *dest = '\0';
105
/* Ignore errors with fixed-iothread=false */
60
- }
106
set_context_errp = fixed_iothread ? errp : NULL;
61
+ return bdrv_get_full_backing_filename_from_filename(backed,
107
- ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
62
+ bs->backing_file,
108
+ ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp);
63
+ errp);
109
if (ret == 0) {
110
aio_context_release(ctx);
111
aio_context_acquire(new_ctx);
112
diff --git a/blockdev.c b/blockdev.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/blockdev.c
115
+++ b/blockdev.c
116
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
117
aio_context_release(aio_context);
118
aio_context_acquire(tmp_context);
119
120
- ret = bdrv_try_set_aio_context(state->old_bs,
121
- aio_context, NULL);
122
+ ret = bdrv_try_change_aio_context(state->old_bs,
123
+ aio_context, NULL, NULL);
124
assert(ret == 0);
125
126
aio_context_release(tmp_context);
127
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
128
goto out;
129
}
130
131
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
132
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
133
old_context = bdrv_get_aio_context(target_bs);
134
aio_context_release(aio_context);
135
aio_context_acquire(old_context);
136
137
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
138
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
139
if (ret < 0) {
140
bdrv_unref(target_bs);
141
aio_context_release(old_context);
142
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
143
return;
144
}
145
146
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
147
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
148
aio_context = bdrv_get_aio_context(bs);
149
old_context = bdrv_get_aio_context(target_bs);
150
aio_context_acquire(old_context);
151
152
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
153
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
154
if (ret < 0) {
155
aio_context_release(old_context);
156
return;
157
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
158
!bdrv_has_zero_init(target_bs)));
159
160
161
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
162
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
163
old_context = bdrv_get_aio_context(target_bs);
164
aio_context_release(aio_context);
165
aio_context_acquire(old_context);
166
167
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
168
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
169
if (ret < 0) {
170
bdrv_unref(target_bs);
171
aio_context_release(old_context);
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
173
174
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
175
176
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
177
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
178
old_context = bdrv_get_aio_context(target_bs);
179
aio_context = bdrv_get_aio_context(bs);
180
aio_context_acquire(old_context);
181
182
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
183
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
184
185
aio_context_release(old_context);
186
aio_context_acquire(aio_context);
187
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
188
old_context = bdrv_get_aio_context(bs);
189
aio_context_acquire(old_context);
190
191
- bdrv_try_set_aio_context(bs, new_context, errp);
192
+ bdrv_try_change_aio_context(bs, new_context, NULL, errp);
193
194
aio_context_release(old_context);
64
}
195
}
65
196
diff --git a/job.c b/job.c
66
void bdrv_register(BlockDriver *bdrv)
197
index XXXXXXX..XXXXXXX 100644
67
@@ -XXX,XX +XXX,XX @@ out:
198
--- a/job.c
68
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
199
+++ b/job.c
69
const char *bdref_key, Error **errp)
200
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
70
{
201
next_aio_context = job->aio_context;
71
- char *backing_filename = g_malloc0(PATH_MAX);
202
/*
72
+ char *backing_filename = NULL;
203
* Coroutine has resumed, but in the meanwhile the job AioContext
73
char *bdref_key_dot;
204
- * might have changed via bdrv_try_set_aio_context(), so we need to move
74
const char *reference = NULL;
205
+ * might have changed via bdrv_try_change_aio_context(), so we need to move
75
int ret = 0;
206
* the coroutine too in the new aiocontext.
76
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
77
*/
207
*/
78
reference = qdict_get_try_str(parent_options, bdref_key);
208
while (qemu_get_current_aio_context() != next_aio_context) {
79
if (reference || qdict_haskey(options, "file.filename")) {
209
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
80
- backing_filename[0] = '\0';
210
index XXXXXXX..XXXXXXX 100644
81
+ /* keep backing_filename NULL */
211
--- a/tests/unit/test-bdrv-drain.c
82
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
212
+++ b/tests/unit/test-bdrv-drain.c
83
qobject_unref(options);
213
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
84
goto free_exit;
214
&error_abort);
85
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
215
86
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
216
bdrv_drained_begin(bs);
87
}
217
- bdrv_try_set_aio_context(bs, ctx_a, &error_abort);
88
218
+ bdrv_try_change_aio_context(bs, ctx_a, NULL, &error_abort);
89
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
219
90
- &local_err);
220
aio_context_acquire(ctx_a);
91
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
221
bdrv_drained_end(bs);
92
if (local_err) {
222
93
ret = -EINVAL;
223
bdrv_drained_begin(bs);
94
error_propagate(errp, local_err);
224
- bdrv_try_set_aio_context(bs, ctx_b, &error_abort);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
225
+ bdrv_try_change_aio_context(bs, ctx_b, NULL, &error_abort);
96
qdict_put_str(options, "driver", bs->backing_format);
226
aio_context_release(ctx_a);
97
}
227
aio_context_acquire(ctx_b);
98
228
- bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort);
99
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
229
+ bdrv_try_change_aio_context(bs, qemu_get_aio_context(), NULL, &error_abort);
100
- reference, options, 0, bs, &child_backing,
230
aio_context_release(ctx_b);
101
- errp);
231
bdrv_drained_end(bs);
102
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
232
103
+ &child_backing, errp);
233
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
104
if (!backing_hd) {
234
index XXXXXXX..XXXXXXX 100644
105
bs->open_flags |= BDRV_O_NO_BACKING;
235
--- a/tests/unit/test-block-iothread.c
106
error_prepend(errp, "Could not open backing file: ");
236
+++ b/tests/unit/test-block-iothread.c
107
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
237
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
108
int is_protocol = 0;
238
filter = bdrv_find_node("filter_node");
109
BlockDriverState *curr_bs = NULL;
239
110
BlockDriverState *retval = NULL;
240
/* Change the AioContext of src */
111
- Error *local_error = NULL;
241
- bdrv_try_set_aio_context(src, ctx, &error_abort);
112
242
+ bdrv_try_change_aio_context(src, ctx, NULL, &error_abort);
113
if (!bs || !bs->drv || !backing_file) {
243
g_assert(bdrv_get_aio_context(src) == ctx);
114
return NULL;
244
g_assert(bdrv_get_aio_context(target) == ctx);
115
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
245
g_assert(bdrv_get_aio_context(filter) == ctx);
116
/* If either of the filename paths is actually a protocol, then
246
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
117
* compare unmodified paths; otherwise make paths relative */
247
118
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
248
/* Change the AioContext of target */
119
+ char *backing_file_full_ret;
249
aio_context_acquire(ctx);
120
+
250
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
121
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
251
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
122
retval = curr_bs->backing->bs;
252
aio_context_release(ctx);
123
break;
253
g_assert(bdrv_get_aio_context(src) == main_ctx);
124
}
254
g_assert(bdrv_get_aio_context(target) == main_ctx);
125
/* Also check against the full backing filename for the image */
255
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
126
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
256
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
127
- &local_error);
257
blk_insert_bs(blk, src, &error_abort);
128
- if (local_error == NULL) {
258
129
- if (strcmp(backing_file, backing_file_full) == 0) {
259
- bdrv_try_set_aio_context(target, ctx, &local_err);
130
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
260
+ bdrv_try_change_aio_context(target, ctx, NULL, &local_err);
131
+ NULL);
261
error_free_or_abort(&local_err);
132
+ if (backing_file_full_ret) {
262
133
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
263
g_assert(blk_get_aio_context(blk) == main_ctx);
134
+ g_free(backing_file_full_ret);
264
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
135
+ if (equal) {
265
/* ...unless we explicitly allow it */
136
retval = curr_bs->backing->bs;
266
aio_context_acquire(ctx);
137
break;
267
blk_set_allow_aio_context_change(blk, true);
138
}
268
- bdrv_try_set_aio_context(target, ctx, &error_abort);
139
- } else {
269
+ bdrv_try_change_aio_context(target, ctx, NULL, &error_abort);
140
- error_free(local_error);
270
aio_context_release(ctx);
141
- local_error = NULL;
271
142
}
272
g_assert(blk_get_aio_context(blk) == ctx);
143
} else {
273
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
144
/* If not an absolute filename path, make it relative to the current
274
145
diff --git a/block/qapi.c b/block/qapi.c
275
aio_context_acquire(ctx);
146
index XXXXXXX..XXXXXXX 100644
276
blk_set_aio_context(blk, main_ctx, &error_abort);
147
--- a/block/qapi.c
277
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
148
+++ b/block/qapi.c
278
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
149
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
279
aio_context_release(ctx);
150
280
151
backing_filename = bs->backing_file;
281
blk_unref(blk);
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
--
282
--
171
2.20.1
283
2.37.3
172
173
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Bin Meng <bin.meng@windriver.com>
2
2
3
While the basic idea is obvious and could be handled by the default
3
libnfs.h declares nfs_fstat() as the following for win32:
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
4
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh,
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
struct __stat64 *st);
10
Message-id: 20190201192935.18394-19-mreitz@redhat.com
7
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
The 'st' parameter should be of type 'struct __stat64'. The
9
codes happen to build successfully for 64-bit Windows, but it
10
does not build for 32-bit Windows.
11
12
Fixes: 6542aa9c75bc ("block: add native support for NFS")
13
Fixes: 18a8056e0bc7 ("block/nfs: cache allocated filesize for read-only files")
14
Signed-off-by: Bin Meng <bin.meng@windriver.com>
15
Message-Id: <20220908132817.1831008-6-bmeng.cn@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
18
---
13
block/nfs.c | 15 +++++++++++++++
19
block/nfs.c | 8 ++++++++
14
1 file changed, 15 insertions(+)
20
1 file changed, 8 insertions(+)
15
21
16
diff --git a/block/nfs.c b/block/nfs.c
22
diff --git a/block/nfs.c b/block/nfs.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nfs.c
24
--- a/block/nfs.c
19
+++ b/block/nfs.c
25
+++ b/block/nfs.c
20
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
26
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
21
bs->full_open_options = opts;
27
int flags, int open_flags, Error **errp)
22
}
28
{
23
29
int64_t ret = -EINVAL;
24
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
30
+#ifdef _WIN32
25
+{
31
+ struct __stat64 st;
26
+ NFSClient *client = bs->opaque;
32
+#else
27
+
33
struct stat st;
28
+ if (client->uid || client->gid) {
34
+#endif
29
+ bdrv_refresh_filename(bs);
35
char *file = NULL, *strp = NULL;
30
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
36
31
+ bs->filename);
37
qemu_mutex_init(&client->mutex);
32
+ return NULL;
38
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
33
+ }
39
BlockReopenQueue *queue, Error **errp)
34
+
40
{
35
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
41
NFSClient *client = state->bs->opaque;
36
+}
42
+#ifdef _WIN32
37
+
43
+ struct __stat64 st;
38
#ifdef LIBNFS_FEATURE_PAGECACHE
44
+#else
39
static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
45
struct stat st;
40
Error **errp)
46
+#endif
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
47
int ret = 0;
42
.bdrv_detach_aio_context = nfs_detach_aio_context,
48
43
.bdrv_attach_aio_context = nfs_attach_aio_context,
49
if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) {
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
--
50
2.20.1
51
2.37.3
51
52
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
While the common implementation for bdrv_dirname() should return NULL
3
The .set_speed callback is not called from coroutine.
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
4
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Message-Id: <20221013123711.620631-2-pbonzini@redhat.com>
11
Message-id: 20190201192935.18394-17-mreitz@redhat.com
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
block/quorum.c | 11 +++++++++++
11
block/backup.c | 2 +-
15
1 file changed, 11 insertions(+)
12
1 file changed, 1 insertion(+), 1 deletion(-)
16
13
17
diff --git a/block/quorum.c b/block/quorum.c
14
diff --git a/block/backup.c b/block/backup.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
16
--- a/block/backup.c
20
+++ b/block/quorum.c
17
+++ b/block/backup.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
18
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_pause(Job *job)
22
bs->full_open_options = opts;
19
}
23
}
20
}
24
21
25
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
22
-static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
26
+{
23
+static void backup_set_speed(BlockJob *job, int64_t speed)
27
+ /* In general, there are multiple BDSs with different dirnames below this
24
{
28
+ * one; so there is no unique dirname we could return (unless all are equal
25
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
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
26
46
--
27
--
47
2.20.1
28
2.37.3
48
49
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-3-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
8
---
4
tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++
9
block/io.c | 4 ++--
5
1 file changed, 32 insertions(+)
10
1 file changed, 2 insertions(+), 2 deletions(-)
6
11
7
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
12
diff --git a/block/io.c b/block/io.c
8
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
9
--- a/tests/test-bdrv-drain.c
14
--- a/block/io.c
10
+++ b/tests/test-bdrv-drain.c
15
+++ b/block/io.c
11
@@ -XXX,XX +XXX,XX @@ static void test_append_to_drained(void)
16
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
12
blk_unref(blk);
17
return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO);
13
}
18
}
14
19
15
+static void test_set_aio_context(void)
20
-int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
16
+{
21
- int64_t bytes, int64_t *pnum)
17
+ BlockDriverState *bs;
22
+int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
18
+ IOThread *a = iothread_new();
23
+ int64_t *pnum)
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
{
24
{
47
int ret;
25
int ret;
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
26
int64_t dummy;
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
--
27
--
58
2.20.1
28
2.37.3
59
60
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Currently, nvme's bdrv_refresh_filename() is an exact copy of null's
3
hmp_block_resize and hmp_screendump are defined as a ".coroutine = true" command,
4
implementation. However, for null, "null-co://" and "null-aio://" are
4
so they must be coroutine_fn.
5
indeed valid filenames -- for nvme, they are not, as a device address is
6
still required.
7
5
8
The correct implementation should generate a filename of the form
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
9
"nvme://[PCI address]/[namespace]" (as the comment above
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
nvme_parse_filename() describes).
8
Message-Id: <20221013123711.620631-4-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block-hmp-cmds.h | 2 +-
13
include/monitor/hmp.h | 3 ++-
14
block/monitor/block-hmp-cmds.c | 2 +-
15
3 files changed, 4 insertions(+), 3 deletions(-)
11
16
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h
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
18
index XXXXXXX..XXXXXXX 100644
22
--- a/block/nvme.c
19
--- a/include/block/block-hmp-cmds.h
23
+++ b/block/nvme.c
20
+++ b/include/block/block-hmp-cmds.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
25
22
void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict);
26
/* Total size of mapped qiov, accessed under dma_map_lock */
23
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
27
int dma_map_count;
24
28
+
25
-void hmp_block_resize(Monitor *mon, const QDict *qdict);
29
+ /* PCI address (required for nvme_refresh_filename()) */
26
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict);
30
+ char *device;
27
void hmp_block_stream(Monitor *mon, const QDict *qdict);
31
} BDRVNVMeState;
28
void hmp_block_passwd(Monitor *mon, const QDict *qdict);
32
29
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
33
#define NVME_BLOCK_OPT_DEVICE "device"
30
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
34
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
31
index XXXXXXX..XXXXXXX 100644
35
32
--- a/include/monitor/hmp.h
36
qemu_co_mutex_init(&s->dma_map_lock);
33
+++ b/include/monitor/hmp.h
37
qemu_co_queue_init(&s->dma_flush_queue);
34
@@ -XXX,XX +XXX,XX @@
38
+ s->device = g_strdup(device);
35
#define HMP_H
39
s->nsid = namespace;
36
40
s->aio_context = bdrv_get_aio_context(bs);
37
#include "qemu/readline.h"
41
ret = event_notifier_init(&s->irq_notifier, 0);
38
+#include "qemu/coroutine.h"
42
@@ -XXX,XX +XXX,XX @@ static void nvme_close(BlockDriverState *bs)
39
#include "qapi/qapi-types-common.h"
43
event_notifier_cleanup(&s->irq_notifier);
40
44
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
41
bool hmp_handle_error(Monitor *mon, Error *err);
45
qemu_vfio_close(s->vfio);
42
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);
46
+
43
void hmp_getfd(Monitor *mon, const QDict *qdict);
47
+ g_free(s->device);
44
void hmp_closefd(Monitor *mon, const QDict *qdict);
45
void hmp_sendkey(Monitor *mon, const QDict *qdict);
46
-void hmp_screendump(Monitor *mon, const QDict *qdict);
47
+void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
48
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
49
void hmp_chardev_change(Monitor *mon, const QDict *qdict);
50
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
51
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/monitor/block-hmp-cmds.c
54
+++ b/block/monitor/block-hmp-cmds.c
55
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
56
hmp_handle_error(mon, err);
48
}
57
}
49
58
50
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
59
-void hmp_block_resize(Monitor *mon, const QDict *qdict)
51
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
60
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict)
52
53
static void nvme_refresh_filename(BlockDriverState *bs)
54
{
61
{
55
- const QDictEntry *e;
62
const char *device = qdict_get_str(qdict, "device");
56
-
63
int64_t size = qdict_get_int(qdict, "size");
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
--
64
--
77
2.20.1
65
2.37.3
78
79
diff view generated by jsdifflib
1
bdrv_drain() must not leave connection_co scheduled, so bs->in_flight
1
From: Alberto Faria <afaria@redhat.com>
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
2
3
ssh_write is only called from ssh_co_writev.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-5-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
10
---
7
block/nbd-client.c | 20 ++++++++++++++++++--
11
block/ssh.c | 6 +++---
8
1 file changed, 18 insertions(+), 2 deletions(-)
12
1 file changed, 3 insertions(+), 3 deletions(-)
9
13
10
diff --git a/block/nbd-client.c b/block/nbd-client.c
14
diff --git a/block/ssh.c b/block/ssh.c
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/block/nbd-client.c
16
--- a/block/ssh.c
13
+++ b/block/nbd-client.c
17
+++ b/block/ssh.c
14
@@ -XXX,XX +XXX,XX @@ void nbd_client_detach_aio_context(BlockDriverState *bs)
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
15
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
19
return ret;
16
}
20
}
17
21
18
+static void nbd_client_attach_aio_context_bh(void *opaque)
22
-static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
19
+{
23
- int64_t offset, size_t size,
20
+ BlockDriverState *bs = opaque;
24
- QEMUIOVector *qiov)
21
+ NBDClientSession *client = nbd_get_client_session(bs);
25
+static coroutine_fn int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
22
+
26
+ int64_t offset, size_t size,
23
+ /* The node is still drained, so we know the coroutine has yielded in
27
+ QEMUIOVector *qiov)
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
{
28
{
34
NBDClientSession *client = nbd_get_client_session(bs);
29
ssize_t r;
35
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
30
size_t written;
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
--
31
--
48
2.20.1
32
2.37.3
49
50
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
This follows what qmp() does, so the output will correspond to the
3
The functions are marked coroutine_fn in the definition.
4
actual QMP command.
5
4
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Message-id: 20190210145736.1486-11-mreitz@redhat.com
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20221013123711.620631-6-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
tests/qemu-iotests/206.out | 56 +++++++++++++++++------------------
11
include/block/block-io.h | 5 +++--
11
tests/qemu-iotests/207.out | 18 +++++------
12
1 file changed, 3 insertions(+), 2 deletions(-)
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
13
20
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/206.out
16
--- a/include/block/block-io.h
23
+++ b/tests/qemu-iotests/206.out
17
+++ b/include/block/block-io.h
24
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
25
=== Successful image creation (defaults) ===
19
void bdrv_aio_cancel_async(BlockAIOCB *acb);
26
20
27
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
21
/* sg packet commands */
28
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
22
-int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
29
{"return": {}}
23
+int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
30
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
24
31
{"return": {}}
25
/* Ensure contents are flushed to disk. */
32
26
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
33
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
27
34
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
28
-int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
35
{"return": {}}
29
+int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
36
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
30
+ int64_t bytes);
37
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
31
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
38
{"return": {}}
32
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
39
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
33
int64_t bytes, int64_t *pnum, int64_t *map,
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
--
34
--
1069
2.20.1
35
2.37.3
1070
1071
diff view generated by jsdifflib
1
Similar to how qemu_co_sleep_ns() allows preemption from an external
1
From: Alberto Faria <afaria@redhat.com>
2
coroutine entry, allow reentering qio_channel_yield() early.
3
2
3
The functions are marked coroutine_fn in the definition.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-7-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
10
---
6
include/io/channel.h | 9 ++++++---
11
include/qemu/coroutine.h | 10 +++++-----
7
io/channel.c | 10 ++++++++++
12
1 file changed, 5 insertions(+), 5 deletions(-)
8
2 files changed, 16 insertions(+), 3 deletions(-)
9
13
10
diff --git a/include/io/channel.h b/include/io/channel.h
14
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/include/io/channel.h
16
--- a/include/qemu/coroutine.h
13
+++ b/include/io/channel.h
17
+++ b/include/qemu/coroutine.h
14
@@ -XXX,XX +XXX,XX @@ void qio_channel_detach_aio_context(QIOChannel *ioc);
18
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock);
15
* addition, no two coroutine can be waiting on the same condition
19
* of a parallel writer, control is transferred to the caller of the current
16
* and channel at the same time.
20
* coroutine.
17
*
18
- * This must only be called from coroutine context
19
+ * This must only be called from coroutine context. It is safe to
20
+ * reenter the coroutine externally while it is waiting; in this
21
+ * case the function will return even if @condition is not yet
22
+ * available.
23
*/
21
*/
24
-void qio_channel_yield(QIOChannel *ioc,
22
-void qemu_co_rwlock_rdlock(CoRwlock *lock);
25
- GIOCondition condition);
23
+void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock);
26
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
27
+ GIOCondition condition);
28
24
29
/**
25
/**
30
* qio_channel_wait:
26
* Write Locks the CoRwlock from a reader. This is a bit more efficient than
31
diff --git a/io/channel.c b/io/channel.c
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock);
32
index XXXXXXX..XXXXXXX 100644
28
* to the caller of the current coroutine; another writer might run while
33
--- a/io/channel.c
29
* @qemu_co_rwlock_upgrade blocks.
34
+++ b/io/channel.c
30
*/
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qio_channel_yield(QIOChannel *ioc,
31
-void qemu_co_rwlock_upgrade(CoRwlock *lock);
36
}
32
+void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock);
37
qio_channel_set_aio_fd_handlers(ioc);
33
38
qemu_coroutine_yield();
34
/**
39
+
35
* Downgrades a write-side critical section to a reader. Downgrading with
40
+ /* Allow interrupting the operation by reentering the coroutine other than
36
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_upgrade(CoRwlock *lock);
41
+ * through the aio_fd_handlers. */
37
* followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but
42
+ if (condition == G_IO_IN && ioc->read_coroutine) {
38
* may also sometimes be necessary for correctness.
43
+ ioc->read_coroutine = NULL;
39
*/
44
+ qio_channel_set_aio_fd_handlers(ioc);
40
-void qemu_co_rwlock_downgrade(CoRwlock *lock);
45
+ } else if (condition == G_IO_OUT && ioc->write_coroutine) {
41
+void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock);
46
+ ioc->write_coroutine = NULL;
42
47
+ qio_channel_set_aio_fd_handlers(ioc);
43
/**
48
+ }
44
* Write Locks the mutex. If the lock cannot be taken immediately because
49
}
45
* of a parallel reader, control is transferred to the caller of the current
50
46
* coroutine.
51
47
*/
48
-void qemu_co_rwlock_wrlock(CoRwlock *lock);
49
+void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock);
50
51
/**
52
* Unlocks the read/write lock and schedules the next coroutine that was
53
* waiting for this lock to be run.
54
*/
55
-void qemu_co_rwlock_unlock(CoRwlock *lock);
56
+void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock);
57
58
typedef struct QemuCoSleep {
59
Coroutine *to_wake;
52
--
60
--
53
2.20.1
61
2.37.3
54
55
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Adding a telnet monitor for no real purpose on a fixed port is not so
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
great. Just use a null monitor instead.
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-8-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/qemu/coroutine.h | 8 +++++---
10
1 file changed, 5 insertions(+), 3 deletions(-)
5
11
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
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
13
index XXXXXXX..XXXXXXX 100644
17
--- a/scripts/qemu.py
14
--- a/include/qemu/coroutine.h
18
+++ b/scripts/qemu.py
15
+++ b/include/qemu/coroutine.h
19
@@ -XXX,XX +XXX,XX @@ class QEMUMachine(object):
16
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size);
20
return False
17
* The same interface as qemu_sendv_recvv(), with added yielding.
21
18
* XXX should mark these as coroutine_fn
22
# This can be used to add an unused monitor instance.
19
*/
23
- def add_monitor_telnet(self, ip, port):
20
-ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
24
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
21
- size_t offset, size_t bytes, bool do_send);
25
+ def add_monitor_null(self):
22
+ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov,
26
self._args.append('-monitor')
23
+ unsigned iov_cnt, size_t offset,
27
- self._args.append(args)
24
+ size_t bytes, bool do_send);
28
+ self._args.append('null')
25
#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
29
26
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
30
def add_fd(self, fd, fdset, opaque, opts=''):
27
#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
31
"""
28
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
32
diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
29
/**
33
index XXXXXXX..XXXXXXX 100755
30
* The same as above, but with just a single buffer
34
--- a/tests/qemu-iotests/045
31
*/
35
+++ b/tests/qemu-iotests/045
32
-ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send);
36
@@ -XXX,XX +XXX,XX @@ class TestSCMFd(iotests.QMPTestCase):
33
+ssize_t coroutine_fn qemu_co_send_recv(int sockfd, void *buf, size_t bytes,
37
qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
34
+ bool do_send);
38
# Add an unused monitor, to verify it works fine when two monitor
35
#define qemu_co_recv(sockfd, buf, bytes) \
39
# instances present
36
qemu_co_send_recv(sockfd, buf, bytes, false)
40
- self.vm.add_monitor_telnet("0",4445)
37
#define qemu_co_send(sockfd, buf, bytes) \
41
+ self.vm.add_monitor_null()
42
self.vm.launch()
43
44
def tearDown(self):
45
--
38
--
46
2.20.1
39
2.37.3
47
48
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
The generic bdrv_dirname() implementation would be able to generate some
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
form of directory name for many NBD nodes, but it would be always wrong.
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Therefore, we have to explicitly make it an error (until NBD has some
5
Message-Id: <20221013123711.620631-9-pbonzini@redhat.com>
6
form of specification for export paths, if it ever will).
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2.h | 14 +++++++-------
10
include/block/block_int-common.h | 12 +++++-------
11
2 files changed, 12 insertions(+), 14 deletions(-)
7
12
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
diff --git a/block/qcow2.h b/block/qcow2.h
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
14
index XXXXXXX..XXXXXXX 100644
19
--- a/block/nbd.c
15
--- a/block/qcow2.h
20
+++ b/block/nbd.c
16
+++ b/block/qcow2.h
21
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
17
@@ -XXX,XX +XXX,XX @@ int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
22
bs->full_open_options = opts;
18
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
23
}
19
bool release_stored, Error **errp);
24
20
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
25
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
21
-bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
26
+{
22
- const char *name,
27
+ /* The generic bdrv_dirname() implementation is able to work out some
23
- uint32_t granularity,
28
+ * directory name for NBD nodes, but that would be wrong. So far there is no
24
- Error **errp);
29
+ * specification for how "export paths" would work, so NBD does not have
25
-int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
30
+ * directory names. */
26
- const char *name,
31
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
27
- Error **errp);
32
+ return NULL;
28
+bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
33
+}
29
+ const char *name,
34
+
30
+ uint32_t granularity,
35
static BlockDriver bdrv_nbd = {
31
+ Error **errp);
36
.format_name = "nbd",
32
+int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
37
.protocol_name = "nbd",
33
+ const char *name,
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
34
+ Error **errp);
39
.bdrv_attach_aio_context = nbd_attach_aio_context,
35
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
40
.bdrv_refresh_filename = nbd_refresh_filename,
36
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
41
.bdrv_co_block_status = nbd_client_co_block_status,
37
uint32_t cluster_size);
42
+ .bdrv_dirname = nbd_dirname,
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block_int-common.h
41
+++ b/include/block/block_int-common.h
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
43
void coroutine_fn (*bdrv_co_drain_end)(BlockDriverState *bs);
44
45
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
46
- bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
47
- const char *name,
48
- uint32_t granularity,
49
- Error **errp);
50
- int (*bdrv_co_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
51
- const char *name,
52
- Error **errp);
53
+ bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
54
+ BlockDriverState *bs, const char *name, uint32_t granularity,
55
+ Error **errp);
56
+ int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
57
+ BlockDriverState *bs, const char *name, Error **errp);
43
};
58
};
44
59
45
static BlockDriver bdrv_nbd_tcp = {
60
static inline bool block_driver_can_compress(BlockDriver *drv)
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
--
61
--
63
2.20.1
62
2.37.3
64
65
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
LUKS encryption reserves clusters for its own payload data. The size of
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
this area must be included in the qemu-img measure calculation so that
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
we arrive at the correct minimum required image size.
5
Message-Id: <20221013123711.620631-10-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
(Ab)use the qcrypto_block_create() API to determine the payload
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
overhead. We discard the payload data that qcrypto thinks will be
9
written to the image.
10
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20190218104525.23674-2-stefanha@redhat.com
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
8
---
16
block/qcow2.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
9
block/qcow2.c | 8 ++++----
17
1 file changed, 71 insertions(+), 1 deletion(-)
10
1 file changed, 4 insertions(+), 4 deletions(-)
18
11
19
diff --git a/block/qcow2.c b/block/qcow2.c
12
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
14
--- a/block/qcow2.c
22
+++ b/block/qcow2.c
15
+++ b/block/qcow2.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
16
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
24
return ret;
17
return pos;
25
}
18
}
26
19
27
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
20
-static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
28
+ size_t headerlen, void *opaque, Error **errp)
21
- int64_t pos)
29
+{
22
+static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
30
+ size_t *headerlenp = opaque;
23
+ QEMUIOVector *qiov, int64_t pos)
31
+
32
+ /* Stash away the payload size */
33
+ *headerlenp = headerlen;
34
+ return 0;
35
+}
36
+
37
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
38
+ size_t offset, const uint8_t *buf, size_t buflen,
39
+ void *opaque, Error **errp)
40
+{
41
+ /* Discard the bytes, we're not actually writing to an image */
42
+ return buflen;
43
+}
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
{
24
{
84
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
25
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
85
uint64_t virtual_size; /* disk size as seen by guest */
26
if (offset < 0) {
86
uint64_t refcount_bits;
27
@@ -XXX,XX +XXX,XX @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
87
uint64_t l2_tables;
28
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
88
+ uint64_t luks_payload_size = 0;
29
}
89
size_t cluster_size;
30
90
int version;
31
-static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
91
char *optstr;
32
- int64_t pos)
92
PreallocMode prealloc;
33
+static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
93
bool has_backing_file;
34
+ QEMUIOVector *qiov, int64_t pos)
94
+ bool has_luks;
35
{
95
36
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
96
/* Parse image creation options */
37
if (offset < 0) {
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
+ }
112
+
113
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
114
+ }
115
+
116
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
117
virtual_size = ROUND_UP(virtual_size, cluster_size);
118
119
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
120
info = g_new(BlockMeasureInfo, 1);
121
info->fully_allocated =
122
qcow2_calc_prealloc_size(virtual_size, cluster_size,
123
- ctz32(refcount_bits));
124
+ ctz32(refcount_bits)) + luks_payload_size;
125
126
/* Remove data clusters that are not required. This overestimates the
127
* required size because metadata needed for the fully allocated file is
128
--
38
--
129
2.20.1
39
2.37.3
130
131
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
The QEMU_PACKED is causing a compiler warning/error with GCC 9:
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
4
Message-Id: <20221013123711.620631-11-pbonzini@redhat.com>
5
CC block/nvme.o
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
7
---
23
block/nvme.c | 2 +-
8
block/blkdebug.c | 2 +-
24
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
25
10
26
diff --git a/block/nvme.c b/block/nvme.c
11
diff --git a/block/blkdebug.c b/block/blkdebug.c
27
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
28
--- a/block/nvme.c
13
--- a/block/blkdebug.c
29
+++ b/block/nvme.c
14
+++ b/block/blkdebug.c
30
@@ -XXX,XX +XXX,XX @@ typedef volatile struct {
15
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
31
uint8_t reserved1[0xec0];
16
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
32
uint8_t cmd_set_specfic[0x100];
17
}
33
uint32_t doorbells[];
18
34
-} QEMU_PACKED NVMeRegs;
19
-static int blkdebug_co_flush(BlockDriverState *bs)
35
+} NVMeRegs;
20
+static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
36
21
{
37
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
22
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
38
23
39
--
24
--
40
2.20.1
25
2.37.3
41
42
diff view generated by jsdifflib
1
The only caller of nbd_read_eof() is nbd_receive_reply(), so it doesn't
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
have to live in the header file, but can move next to its caller.
3
2
4
Also add the missing coroutine_fn to the function and its caller.
3
get_cluster_offset() and decompress_cluster() are only called from
4
the read and write paths.
5
5
6
The validity of these was double-checked with Alberto Faria's static analyzer.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20221013123711.620631-12-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
12
---
9
include/block/nbd.h | 3 ++-
13
block/qcow.c | 15 +++++++++------
10
nbd/nbd-internal.h | 19 -------------------
14
1 file changed, 9 insertions(+), 6 deletions(-)
11
nbd/client.c | 22 +++++++++++++++++++++-
12
3 files changed, 23 insertions(+), 21 deletions(-)
13
15
14
diff --git a/include/block/nbd.h b/include/block/nbd.h
16
diff --git a/block/qcow.c b/block/qcow.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/nbd.h
18
--- a/block/qcow.c
17
+++ b/include/block/nbd.h
19
+++ b/block/qcow.c
18
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
19
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
21
20
Error **errp);
22
static QemuOptsList qcow_create_opts;
21
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
23
22
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
24
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
23
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
25
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
24
+ Error **errp);
26
+ uint64_t cluster_offset);
25
int nbd_client(int fd);
27
26
int nbd_disconnect(int fd);
28
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
27
int nbd_errno_to_system_errno(int err);
29
{
28
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
30
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
29
index XXXXXXX..XXXXXXX 100644
31
* return 0 if not allocated, 1 if *result is assigned, and negative
30
--- a/nbd/nbd-internal.h
32
* errno on failure.
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
*/
33
*/
58
diff --git a/nbd/client.c b/nbd/client.c
34
-static int get_cluster_offset(BlockDriverState *bs,
59
index XXXXXXX..XXXXXXX 100644
35
- uint64_t offset, int allocate,
60
--- a/nbd/client.c
36
- int compressed_size,
61
+++ b/nbd/client.c
37
- int n_start, int n_end, uint64_t *result)
62
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
38
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
39
+ uint64_t offset, int allocate,
40
+ int compressed_size,
41
+ int n_start, int n_end,
42
+ uint64_t *result)
43
{
44
BDRVQcowState *s = bs->opaque;
45
int min_index, i, j, l1_index, l2_index, ret;
46
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
63
return 0;
47
return 0;
64
}
48
}
65
49
66
+/* nbd_read_eof
50
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
67
+ * Tries to read @size bytes from @ioc.
51
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
68
+ * Returns 1 on success
52
+ uint64_t cluster_offset)
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
{
53
{
94
int ret;
54
BDRVQcowState *s = bs->opaque;
95
const char *type;
55
int ret, csize;
96
--
56
--
97
2.20.1
57
2.37.3
98
99
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
The validity of these was double-checked with Alberto Faria's static
6
aio_co_wake() really enters the coroutine immediately here: These
4
analyzer.
7
handlers are never run in coroutine context, and we're in the right
8
AioContext because qio_channel_attach_aio_context() asserts that the
9
handlers are inactive.
10
5
11
To make these conditions more obvious, assert the right AioContext.
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
7
Message-Id: <20221013123711.620631-13-pbonzini@redhat.com>
13
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
10
---
16
io/channel.c | 12 ++++++------
11
block/qcow2.h | 18 +++++++++---------
17
1 file changed, 6 insertions(+), 6 deletions(-)
12
block/qcow2-bitmap.c | 4 ++--
13
block/qcow2-cluster.c | 21 ++++++++++++---------
14
block/qcow2-refcount.c | 8 ++++----
15
4 files changed, 27 insertions(+), 24 deletions(-)
18
16
19
diff --git a/io/channel.c b/io/channel.c
17
diff --git a/block/qcow2.h b/block/qcow2.h
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/io/channel.c
19
--- a/block/qcow2.h
22
+++ b/io/channel.c
20
+++ b/block/qcow2.h
23
@@ -XXX,XX +XXX,XX @@ off_t qio_channel_io_seek(QIOChannel *ioc,
21
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
22
Error **errp);
23
24
/* qcow2-refcount.c functions */
25
-int qcow2_refcount_init(BlockDriverState *bs);
26
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
27
void qcow2_refcount_close(BlockDriverState *bs);
28
29
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
30
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
31
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
32
BlockDriverAmendStatusCB *status_cb,
33
void *cb_opaque, Error **errp);
34
-int qcow2_shrink_reftable(BlockDriverState *bs);
35
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
36
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
37
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
38
39
/* qcow2-cluster.c functions */
40
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
41
bool exact_size);
42
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
43
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
44
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
45
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
46
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
47
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
48
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
49
unsigned int *bytes,
50
uint64_t *host_offset, QCowL2Meta **m);
51
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
52
- uint64_t offset,
53
- int compressed_size,
54
- uint64_t *host_offset);
55
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
56
+ uint64_t offset,
57
+ int compressed_size,
58
+ uint64_t *host_offset);
59
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
60
uint64_t *coffset, int *csize);
61
62
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_discard(Qcow2Cache *c, void *table);
63
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
64
void **refcount_table,
65
int64_t *refcount_table_size);
66
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
67
- Error **errp);
68
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
69
+ bool *header_updated, Error **errp);
70
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
71
Qcow2BitmapInfoList **info_list, Error **errp);
72
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
73
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/qcow2-bitmap.c
76
+++ b/block/qcow2-bitmap.c
77
@@ -XXX,XX +XXX,XX @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
78
* If header_updated is not NULL then it is set appropriately regardless of
79
* the return value.
80
*/
81
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
82
- Error **errp)
83
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
84
+ bool *header_updated, Error **errp)
85
{
86
BDRVQcow2State *s = bs->opaque;
87
Qcow2BitmapList *bm_list;
88
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/block/qcow2-cluster.c
91
+++ b/block/qcow2-cluster.c
92
@@ -XXX,XX +XXX,XX @@
93
#include "qemu/memalign.h"
94
#include "trace.h"
95
96
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
97
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
98
+ uint64_t exact_size)
99
{
100
BDRVQcow2State *s = bs->opaque;
101
int new_l1_size, i, ret;
102
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
103
*
104
* Return 0 on success and -errno in error cases
105
*/
106
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
107
- uint64_t offset,
108
- int compressed_size,
109
- uint64_t *host_offset)
110
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
111
+ uint64_t offset,
112
+ int compressed_size,
113
+ uint64_t *host_offset)
114
{
115
BDRVQcow2State *s = bs->opaque;
116
int l2_index, ret;
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
118
*
119
* -errno: in error cases
120
*/
121
-static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
122
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
123
+static int coroutine_fn handle_copied(BlockDriverState *bs,
124
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
125
+ QCowL2Meta **m)
126
{
127
BDRVQcow2State *s = bs->opaque;
128
int l2_index;
129
@@ -XXX,XX +XXX,XX @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
130
*
131
* -errno: in error cases
132
*/
133
-static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
134
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
135
+static int coroutine_fn handle_alloc(BlockDriverState *bs,
136
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
137
+ QCowL2Meta **m)
138
{
139
BDRVQcow2State *s = bs->opaque;
140
int l2_index;
141
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/block/qcow2-refcount.c
144
+++ b/block/qcow2-refcount.c
145
@@ -XXX,XX +XXX,XX @@ static void update_max_refcount_table_index(BDRVQcow2State *s)
146
s->max_refcount_table_index = i;
24
}
147
}
25
148
26
149
-int qcow2_refcount_init(BlockDriverState *bs)
27
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
150
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
28
-
29
static void qio_channel_restart_read(void *opaque)
30
{
151
{
31
QIOChannel *ioc = opaque;
152
BDRVQcow2State *s = bs->opaque;
32
Coroutine *co = ioc->read_coroutine;
153
unsigned int refcount_table_size2, i;
33
154
@@ -XXX,XX +XXX,XX @@ static int64_t get_refblock_offset(BlockDriverState *bs, uint64_t offset)
34
- ioc->read_coroutine = NULL;
155
return covering_refblock_offset;
35
- qio_channel_set_aio_fd_handlers(ioc);
36
+ /* Assert that aio_co_wake() reenters the coroutine directly */
37
+ assert(qemu_get_current_aio_context() ==
38
+ qemu_coroutine_get_aio_context(co));
39
aio_co_wake(co);
40
}
156
}
41
157
42
@@ -XXX,XX +XXX,XX @@ static void qio_channel_restart_write(void *opaque)
158
-static int qcow2_discard_refcount_block(BlockDriverState *bs,
43
QIOChannel *ioc = opaque;
159
- uint64_t discard_block_offs)
44
Coroutine *co = ioc->write_coroutine;
160
+static int coroutine_fn
45
161
+qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
46
- ioc->write_coroutine = NULL;
162
{
47
- qio_channel_set_aio_fd_handlers(ioc);
163
BDRVQcow2State *s = bs->opaque;
48
+ /* Assert that aio_co_wake() reenters the coroutine directly */
164
int64_t refblock_offs;
49
+ assert(qemu_get_current_aio_context() ==
165
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
50
+ qemu_coroutine_get_aio_context(co));
166
return 0;
51
aio_co_wake(co);
52
}
167
}
53
168
169
-int qcow2_shrink_reftable(BlockDriverState *bs)
170
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
171
{
172
BDRVQcow2State *s = bs->opaque;
173
uint64_t *reftable_tmp =
54
--
174
--
55
2.20.1
175
2.37.3
56
57
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Some follow-up patches will rework the way bs->full_open_options is
3
The validity of these was double-checked with Alberto Faria's static analyzer.
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
4
9
However, by implementing bdrv_gather_child_options(), block drivers will
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
still be able to override the way the full_open_options of their
6
Message-Id: <20221013123711.620631-14-pbonzini@redhat.com>
11
children are incorporated into their own.
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/vmdk.c | 34 +++++++++++++++++-----------------
11
1 file changed, 17 insertions(+), 17 deletions(-)
12
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
13
diff --git a/block/vmdk.c b/block/vmdk.c
131
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
132
--- a/block/vmdk.c
15
--- a/block/vmdk.c
133
+++ b/block/vmdk.c
16
+++ b/block/vmdk.c
134
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
135
#include "qapi/error.h"
18
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
136
#include "block/block_int.h"
19
* it for call to write user data in the request.
137
#include "sysemu/block-backend.h"
20
*/
138
+#include "qapi/qmp/qdict.h"
21
-static int get_whole_cluster(BlockDriverState *bs,
139
#include "qapi/qmp/qerror.h"
22
- VmdkExtent *extent,
140
#include "qemu/error-report.h"
23
- uint64_t cluster_offset,
141
#include "qemu/module.h"
24
- uint64_t offset,
142
@@ -XXX,XX +XXX,XX @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
25
- uint64_t skip_start_bytes,
143
return 0;
26
- uint64_t skip_end_bytes,
27
- bool zeroed)
28
+static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
29
+ VmdkExtent *extent,
30
+ uint64_t cluster_offset,
31
+ uint64_t offset,
32
+ uint64_t skip_start_bytes,
33
+ uint64_t skip_end_bytes,
34
+ bool zeroed)
35
{
36
int ret = VMDK_OK;
37
int64_t cluster_bytes;
38
@@ -XXX,XX +XXX,XX @@ exit:
39
return ret;
144
}
40
}
145
41
146
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
42
-static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
147
+ bool backing_overridden)
43
- uint32_t offset)
148
+{
44
+static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
149
+ /* No children but file and backing can be explicitly specified (TODO) */
45
+ uint32_t offset)
150
+ qdict_put(target, "file",
46
{
151
+ qobject_ref(bs->file->bs->full_open_options));
47
offset = cpu_to_le32(offset);
152
+
48
/* update L2 table */
153
+ if (backing_overridden) {
49
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
154
+ if (bs->backing) {
50
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
155
+ qdict_put(target, "backing",
51
* VMDK_ERROR if failed.
156
+ qobject_ref(bs->backing->bs->full_open_options));
52
*/
157
+ } else {
53
-static int get_cluster_offset(BlockDriverState *bs,
158
+ qdict_put_null(target, "backing");
54
- VmdkExtent *extent,
159
+ }
55
- VmdkMetaData *m_data,
160
+ }
56
- uint64_t offset,
161
+}
57
- bool allocate,
162
+
58
- uint64_t *cluster_offset,
163
static QemuOptsList vmdk_create_opts = {
59
- uint64_t skip_start_bytes,
164
.name = "vmdk-create-opts",
60
- uint64_t skip_end_bytes)
165
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
61
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
166
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
62
+ VmdkExtent *extent,
167
.bdrv_get_specific_info = vmdk_get_specific_info,
63
+ VmdkMetaData *m_data,
168
.bdrv_refresh_limits = vmdk_refresh_limits,
64
+ uint64_t offset,
169
.bdrv_get_info = vmdk_get_info,
65
+ bool allocate,
170
+ .bdrv_gather_child_options = vmdk_gather_child_options,
66
+ uint64_t *cluster_offset,
171
67
+ uint64_t skip_start_bytes,
172
.supports_backing = true,
68
+ uint64_t skip_end_bytes)
173
.create_opts = &vmdk_create_opts,
69
{
70
unsigned int l1_index, l2_offset, l2_index;
71
int min_index, i, j;
174
--
72
--
175
2.20.1
73
2.37.3
176
177
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
If there's an error in commit_start() then the block job must be
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
deleted before replacing commit_top_bs, otherwise it will fail because
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
of lack of permissions. This happens since the permission system was
5
Message-Id: <20221013123711.620631-15-pbonzini@redhat.com>
6
introduced in 8dfba2797761d8a43744e4e6571c8175e448a478.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
8
Fortunately this bug doesn't seem to be possible to reproduce at the
9
moment without changing the code.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
8
---
14
block/commit.c | 4 +++-
9
block/commit.c | 2 +-
15
1 file changed, 3 insertions(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
11
17
diff --git a/block/commit.c b/block/commit.c
12
diff --git a/block/commit.c b/block/commit.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/block/commit.c
14
--- a/block/commit.c
20
+++ b/block/commit.c
15
+++ b/block/commit.c
21
@@ -XXX,XX +XXX,XX @@ fail:
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
22
if (s->top) {
23
blk_unref(s->top);
24
}
17
}
25
+ job_early_fail(&s->common.job);
18
26
+ /* commit_top_bs has to be replaced after deleting the block job,
19
if (base_len < len) {
27
+ * otherwise this would fail because of lack of permissions. */
20
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
28
if (commit_top_bs) {
21
+ ret = blk_co_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
29
bdrv_replace_node(commit_top_bs, top, &error_abort);
22
if (ret) {
30
}
23
return ret;
31
- job_early_fail(&s->common.job);
24
}
32
}
33
34
35
--
25
--
36
2.20.1
26
2.37.3
37
38
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
bdrv_refresh_filename() should simply skip all implicit nodes. They are
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
supposed to be invisible to the user, so they should not appear in
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
filename information.
5
Message-Id: <20221013123711.620631-16-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@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
---
8
---
13
block.c | 14 ++++++++++++++
9
block.c | 2 +-
14
1 file changed, 14 insertions(+)
10
block/io.c | 4 ++--
11
2 files changed, 3 insertions(+), 3 deletions(-)
15
12
16
diff --git a/block.c b/block.c
13
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
15
--- a/block.c
19
+++ b/block.c
16
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
17
@@ -XXX,XX +XXX,XX @@ create_file_fallback_zero_first_sector(BlockBackend *blk,
21
bdrv_refresh_filename(child->bs);
18
19
bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE);
20
if (bytes_to_clear) {
21
- ret = blk_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
22
+ ret = blk_co_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
23
if (ret < 0) {
24
error_setg_errno(errp, -ret,
25
"Failed to clear the new image's first sector");
26
diff --git a/block/io.c b/block/io.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/io.c
29
+++ b/block/io.c
30
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
31
return 1;
22
}
32
}
23
33
24
+ if (bs->implicit) {
34
- ret = bdrv_common_block_status_above(bs, NULL, false, false, offset,
25
+ /* For implicit nodes, just copy everything from the single child */
35
- bytes, &pnum, NULL, NULL, NULL);
26
+ child = QLIST_FIRST(&bs->children);
36
+ ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset,
27
+ assert(QLIST_NEXT(child, next) == NULL);
37
+ bytes, &pnum, NULL, NULL, NULL);
28
+
38
29
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
39
if (ret < 0) {
30
+ child->bs->exact_filename);
40
return ret;
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
--
41
--
42
2.20.1
42
2.37.3
43
44
diff view generated by jsdifflib
1
From: Jeff Cody <jcody@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
I'll not be involved with day-to-day qemu development, and John
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Snow is a block jobs wizard. Have him take over block job
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
maintainership duties.
5
Message-Id: <20221013123711.620631-17-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
8
---
12
MAINTAINERS | 4 ++--
9
block/mirror.c | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
10
1 file changed, 2 insertions(+), 2 deletions(-)
14
11
15
diff --git a/MAINTAINERS b/MAINTAINERS
12
diff --git a/block/mirror.c b/block/mirror.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
14
--- a/block/mirror.c
18
+++ b/MAINTAINERS
15
+++ b/block/mirror.c
19
@@ -XXX,XX +XXX,XX @@ F: include/scsi/*
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
20
F: scsi/*
17
* active layer. */
21
18
if (s->base == blk_bs(s->target)) {
22
Block Jobs
19
if (s->bdev_length > target_length) {
23
-M: Jeff Cody <jcody@redhat.com>
20
- ret = blk_truncate(s->target, s->bdev_length, false,
24
+M: John Snow <jsnow@redhat.com>
21
- PREALLOC_MODE_OFF, 0, NULL);
25
L: qemu-block@nongnu.org
22
+ ret = blk_co_truncate(s->target, s->bdev_length, false,
26
S: Supported
23
+ PREALLOC_MODE_OFF, 0, NULL);
27
F: blockjob.c
24
if (ret < 0) {
28
@@ -XXX,XX +XXX,XX @@ F: block/commit.c
25
goto immediate_exit;
29
F: block/stream.c
26
}
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
--
27
--
38
2.20.1
28
2.37.3
39
40
diff view generated by jsdifflib
1
Instead of using the convenience wrapper qio_channel_read_all_eof(), use
1
From: Alberto Faria <afaria@redhat.com>
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
2
7
This moves the bdrv_dec/inc_in_flight() pair into nbd_read_eof(), so
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
8
that connection_co will always sit in this exact qio_channel_yield()
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
call when bdrv_drain() returns.
5
Message-Id: <20221013123711.620631-18-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/parallels.c | 28 ++++++++++++++--------------
10
1 file changed, 14 insertions(+), 14 deletions(-)
10
11
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
diff --git a/block/parallels.c b/block/parallels.c
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
13
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/nbd.h
14
--- a/block/parallels.c
22
+++ b/include/block/nbd.h
15
+++ b/block/parallels.c
23
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
16
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
24
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
17
* force the safer-but-slower fallocate.
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
*/
18
*/
47
- bdrv_dec_in_flight(s->bs);
19
if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
48
assert(s->reply.handle == 0);
20
- ret = bdrv_truncate(bs->file,
49
- ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
21
- (s->data_end + space) << BDRV_SECTOR_BITS,
50
- bdrv_inc_in_flight(s->bs);
22
- false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
51
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err);
23
- NULL);
52
24
+ ret = bdrv_co_truncate(bs->file,
53
if (local_err) {
25
+ (s->data_end + space) << BDRV_SECTOR_BITS,
54
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
26
+ false, PREALLOC_MODE_OFF,
55
diff --git a/nbd/client.c b/nbd/client.c
27
+ BDRV_REQ_ZERO_WRITE, NULL);
56
index XXXXXXX..XXXXXXX 100644
28
if (ret == -ENOTSUP) {
57
--- a/nbd/client.c
29
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
58
+++ b/nbd/client.c
30
}
59
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
31
}
60
* negative errno on failure (errp is set)
32
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
61
*/
33
- ret = bdrv_pwrite_zeroes(bs->file,
62
static inline int coroutine_fn
34
- s->data_end << BDRV_SECTOR_BITS,
63
-nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
35
- space << BDRV_SECTOR_BITS, 0);
64
+nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
36
+ ret = bdrv_co_pwrite_zeroes(bs->file,
65
+ Error **errp)
37
+ s->data_end << BDRV_SECTOR_BITS,
66
{
38
+ space << BDRV_SECTOR_BITS, 0);
67
- int ret;
39
}
68
+ bool partial = false;
40
if (ret < 0) {
69
41
return ret;
70
assert(size);
42
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
71
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
43
if (off + to_write > s->header_size) {
72
- if (ret < 0) {
44
to_write = s->header_size - off;
73
- ret = -EIO;
45
}
74
+ while (size > 0) {
46
- ret = bdrv_pwrite(bs->file, off, to_write, (uint8_t *)s->header + off,
75
+ struct iovec iov = { .iov_base = buffer, .iov_len = size };
47
- 0);
76
+ ssize_t len;
48
+ ret = bdrv_co_pwrite(bs->file, off, to_write,
77
+
49
+ (uint8_t *)s->header + off, 0);
78
+ len = qio_channel_readv(ioc, &iov, 1, errp);
50
if (ret < 0) {
79
+ if (len == QIO_CHANNEL_ERR_BLOCK) {
51
qemu_co_mutex_unlock(&s->lock);
80
+ bdrv_dec_in_flight(bs);
52
return ret;
81
+ qio_channel_yield(ioc, G_IO_IN);
53
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
82
+ bdrv_inc_in_flight(bs);
54
* In order to really repair the image, we must shrink it.
83
+ continue;
55
* That means we have to pass exact=true.
84
+ } else if (len < 0) {
56
*/
85
+ return -EIO;
57
- ret = bdrv_truncate(bs->file, res->image_end_offset, true,
86
+ } else if (len == 0) {
58
- PREALLOC_MODE_OFF, 0, &local_err);
87
+ if (partial) {
59
+ ret = bdrv_co_truncate(bs->file, res->image_end_offset, true,
88
+ error_setg(errp,
60
+ PREALLOC_MODE_OFF, 0, &local_err);
89
+ "Unexpected end-of-file before all bytes were read");
61
if (ret < 0) {
90
+ return -EIO;
62
error_report_err(local_err);
91
+ } else {
63
res->check_errors++;
92
+ return 0;
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
93
+ }
65
memset(tmp, 0, sizeof(tmp));
94
+ }
66
memcpy(tmp, &header, sizeof(header));
95
+
67
96
+ partial = true;
68
- ret = blk_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
97
+ size -= len;
69
+ ret = blk_co_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
98
+ buffer = (uint8_t*) buffer + len;
70
if (ret < 0) {
71
goto exit;
99
}
72
}
100
- return ret;
73
- ret = blk_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
101
+ return 1;
74
- (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
102
}
75
+ ret = blk_co_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
103
76
+ (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
104
/* nbd_receive_reply
77
if (ret < 0) {
105
+ *
78
goto exit;
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
}
79
}
127
--
80
--
128
2.20.1
81
2.37.3
129
130
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
L1 table entries have a field to store the offset of an L2 table.
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
The rest of the bits of the entry are currently reserved except from
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
bit 63, which stores the COPIED flag.
5
Message-Id: <20221013123711.620631-19-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
8
---
20
block/qcow2-cluster.c | 3 +++
9
block/qcow.c | 45 +++++++++++++++++++++++----------------------
21
1 file changed, 3 insertions(+)
10
1 file changed, 23 insertions(+), 22 deletions(-)
22
11
23
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
12
diff --git a/block/qcow.c b/block/qcow.c
24
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2-cluster.c
14
--- a/block/qcow.c
26
+++ b/block/qcow2-cluster.c
15
+++ b/block/qcow.c
27
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
28
goto fail;
17
s->l1_table[l1_index] = l2_offset;
18
tmp = cpu_to_be64(l2_offset);
19
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
20
- ret = bdrv_pwrite_sync(bs->file,
21
- s->l1_table_offset + l1_index * sizeof(tmp),
22
- sizeof(tmp), &tmp, 0);
23
+ ret = bdrv_co_pwrite_sync(bs->file,
24
+ s->l1_table_offset + l1_index * sizeof(tmp),
25
+ sizeof(tmp), &tmp, 0);
26
if (ret < 0) {
27
return ret;
28
}
29
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
30
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
31
if (new_l2_table) {
32
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
33
- ret = bdrv_pwrite_sync(bs->file, l2_offset,
34
- s->l2_size * sizeof(uint64_t), l2_table, 0);
35
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset,
36
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
37
if (ret < 0) {
38
return ret;
39
}
40
} else {
41
- ret = bdrv_pread(bs->file, l2_offset, s->l2_size * sizeof(uint64_t),
42
- l2_table, 0);
43
+ ret = bdrv_co_pread(bs->file, l2_offset,
44
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
45
if (ret < 0) {
46
return ret;
47
}
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
49
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
50
/* write the cluster content */
51
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
52
- ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_size,
53
- s->cluster_cache, 0);
54
+ ret = bdrv_co_pwrite(bs->file, cluster_offset, s->cluster_size,
55
+ s->cluster_cache, 0);
56
if (ret < 0) {
57
return ret;
58
}
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
60
if (cluster_offset + s->cluster_size > INT64_MAX) {
61
return -E2BIG;
62
}
63
- ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
64
- false, PREALLOC_MODE_OFF, 0, NULL);
65
+ ret = bdrv_co_truncate(bs->file,
66
+ cluster_offset + s->cluster_size,
67
+ false, PREALLOC_MODE_OFF, 0, NULL);
68
if (ret < 0) {
69
return ret;
70
}
71
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
72
return -EIO;
73
}
74
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
75
- ret = bdrv_pwrite(bs->file, cluster_offset + i,
76
- BDRV_SECTOR_SIZE,
77
- s->cluster_data, 0);
78
+ ret = bdrv_co_pwrite(bs->file, cluster_offset + i,
79
+ BDRV_SECTOR_SIZE,
80
+ s->cluster_data, 0);
81
if (ret < 0) {
82
return ret;
83
}
84
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
85
} else {
86
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
87
}
88
- ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
89
- sizeof(tmp), &tmp, 0);
90
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
91
+ sizeof(tmp), &tmp, 0);
92
if (ret < 0) {
93
return ret;
94
}
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn decompress_cluster(BlockDriverState *bs,
96
csize = cluster_offset >> (63 - s->cluster_bits);
97
csize &= (s->cluster_size - 1);
98
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
99
- ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
100
+ ret = bdrv_co_pread(bs->file, coffset, csize, s->cluster_data, 0);
101
if (ret < 0)
102
return -1;
103
if (decompress_buffer(s->cluster_cache, s->cluster_size,
104
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
29
}
105
}
30
106
31
+ /* The offset must fit in the offset field of the L1 table entry */
107
/* write all the data */
32
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
108
- ret = blk_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
33
+
109
+ ret = blk_co_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
34
/* If we're allocating the table at offset 0 then something is wrong */
110
if (ret < 0) {
35
if (l2_offset == 0) {
111
goto exit;
36
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
112
}
113
114
if (qcow_opts->has_backing_file) {
115
- ret = blk_pwrite(qcow_blk, sizeof(header), backing_filename_len,
116
- qcow_opts->backing_file, 0);
117
+ ret = blk_co_pwrite(qcow_blk, sizeof(header), backing_filename_len,
118
+ qcow_opts->backing_file, 0);
119
if (ret < 0) {
120
goto exit;
121
}
122
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
123
tmp = g_malloc0(BDRV_SECTOR_SIZE);
124
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
125
i++) {
126
- ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
127
- BDRV_SECTOR_SIZE, tmp, 0);
128
+ ret = blk_co_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
129
+ BDRV_SECTOR_SIZE, tmp, 0);
130
if (ret < 0) {
131
g_free(tmp);
132
goto exit;
37
--
133
--
38
2.20.1
134
2.37.3
39
40
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
If the backing file is overridden, this most probably does change the
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
guest-visible data of a BDS. Therefore, we will need to consider this
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
in bdrv_refresh_filename().
5
Message-Id: <20221013123711.620631-20-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2-cluster.c | 8 ++++----
10
block/qcow2-refcount.c | 10 +++++-----
11
block/qcow2-snapshot.c | 6 +++---
12
block/qcow2.c | 24 ++++++++++++------------
13
4 files changed, 24 insertions(+), 24 deletions(-)
6
14
7
To see whether it has been overridden, we might want to compare
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
8
bs->backing_file and bs->backing->bs->filename. However,
9
bs->backing_file is changed by bdrv_set_backing_hd() (which is just used
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>
61
Message-id: 20190201192935.18394-5-mreitz@redhat.com
62
Signed-off-by: Max Reitz <mreitz@redhat.com>
63
---
64
include/block/block_int.h | 4 ++++
65
block.c | 19 +++++++++++++++++++
66
block/qcow.c | 7 +++++--
67
block/qcow2.c | 10 +++++++---
68
block/qed.c | 7 +++++--
69
block/vmdk.c | 6 ++++--
70
6 files changed, 44 insertions(+), 9 deletions(-)
71
72
diff --git a/include/block/block_int.h b/include/block/block_int.h
73
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
74
--- a/include/block/block_int.h
17
--- a/block/qcow2-cluster.c
75
+++ b/include/block/block_int.h
18
+++ b/block/qcow2-cluster.c
76
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
19
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
77
char filename[PATH_MAX];
20
#endif
78
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
21
79
this file image */
22
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
80
+ /* The backing filename indicated by the image header; if we ever
23
- ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
81
+ * open this file, then this is replaced by the resulting BDS's
24
- new_l1_size * L1E_SIZE,
82
+ * filename (i.e. after a bdrv_refresh_filename() run). */
25
- (s->l1_size - new_l1_size) * L1E_SIZE, 0);
83
+ char auto_backing_file[PATH_MAX];
26
+ ret = bdrv_co_pwrite_zeroes(bs->file,
84
char backing_format[16]; /* if non-zero and backing_file exists */
27
+ s->l1_table_offset + new_l1_size * L1E_SIZE,
85
28
+ (s->l1_size - new_l1_size) * L1E_SIZE, 0);
86
QDict *full_open_options;
29
if (ret < 0) {
87
diff --git a/block.c b/block.c
30
goto fail;
31
}
32
33
- ret = bdrv_flush(bs->file->bs);
34
+ ret = bdrv_co_flush(bs->file->bs);
35
if (ret < 0) {
36
goto fail;
37
}
38
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
88
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
89
--- a/block.c
40
--- a/block/qcow2-refcount.c
90
+++ b/block.c
41
+++ b/block/qcow2-refcount.c
91
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
42
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
92
char *bdref_key_dot;
93
const char *reference = NULL;
94
int ret = 0;
95
+ bool implicit_backing = false;
96
BlockDriverState *backing_hd;
97
QDict *options;
98
QDict *tmp_parent_options = NULL;
99
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
100
qobject_unref(options);
101
goto free_exit;
102
} else {
103
+ if (qdict_size(options) == 0) {
104
+ /* If the user specifies options that do not modify the
105
+ * backing file's behavior, we might still consider it the
106
+ * implicit backing file. But it's easier this way, and
107
+ * just specifying some of the backing BDS's options is
108
+ * only possible with -drive anyway (otherwise the QAPI
109
+ * schema forces the user to specify everything). */
110
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
111
+ }
112
+
113
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
114
&local_err);
115
if (local_err) {
116
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
117
}
118
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
119
120
+ if (implicit_backing) {
121
+ bdrv_refresh_filename(backing_hd);
122
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
123
+ backing_hd->filename);
124
+ }
125
+
126
/* Hook up the backing file link; drop our reference, bs owns the
127
* backing_hd reference now */
128
bdrv_set_backing_hd(bs, backing_hd, &local_err);
129
@@ -XXX,XX +XXX,XX @@ int bdrv_change_backing_file(BlockDriverState *bs,
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;
43
goto fail;
152
}
44
}
153
ret = bdrv_pread(bs->file, header.backing_file_offset,
45
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
154
- bs->backing_file, len);
46
- ret = bdrv_pread(bs->file, s->refcount_table_offset,
155
+ bs->auto_backing_file, len);
47
- refcount_table_size2, s->refcount_table, 0);
48
+ ret = bdrv_co_pread(bs->file, s->refcount_table_offset,
49
+ refcount_table_size2, s->refcount_table, 0);
156
if (ret < 0) {
50
if (ret < 0) {
157
goto fail;
51
goto fail;
158
}
52
}
159
- bs->backing_file[len] = '\0';
53
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
160
+ bs->auto_backing_file[len] = '\0';
54
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
161
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
162
+ bs->auto_backing_file);
163
}
55
}
164
56
165
/* Disable migration when qcow images are used */
57
- ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset,
58
- s->refcount_table_size * REFTABLE_ENTRY_SIZE,
59
- reftable_tmp, 0);
60
+ ret = bdrv_co_pwrite_sync(bs->file, s->refcount_table_offset,
61
+ s->refcount_table_size * REFTABLE_ENTRY_SIZE,
62
+ reftable_tmp, 0);
63
/*
64
* If the write in the reftable failed the image may contain a partially
65
* overwritten reftable. In this case it would be better to clear the
66
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/qcow2-snapshot.c
69
+++ b/block/qcow2-snapshot.c
70
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
71
} QEMU_PACKED snapshot_table_pointer;
72
73
/* qcow2_do_open() discards this information in check mode */
74
- ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
75
- sizeof(snapshot_table_pointer), &snapshot_table_pointer,
76
- 0);
77
+ ret = bdrv_co_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
78
+ sizeof(snapshot_table_pointer), &snapshot_table_pointer,
79
+ 0);
80
if (ret < 0) {
81
result->check_errors++;
82
fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
166
diff --git a/block/qcow2.c b/block/qcow2.c
83
diff --git a/block/qcow2.c b/block/qcow2.c
167
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
85
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
86
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
88
uint64_t l1_vm_state_index;
89
bool update_header = false;
90
91
- ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
92
+ ret = bdrv_co_pread(bs->file, 0, sizeof(header), &header, 0);
93
if (ret < 0) {
94
error_setg_errno(errp, -ret, "Could not read qcow2 header");
95
goto fail;
96
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
97
if (header.header_length > sizeof(header)) {
98
s->unknown_header_fields_size = header.header_length - sizeof(header);
99
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
100
- ret = bdrv_pread(bs->file, sizeof(header),
101
- s->unknown_header_fields_size,
102
- s->unknown_header_fields, 0);
103
+ ret = bdrv_co_pread(bs->file, sizeof(header),
104
+ s->unknown_header_fields_size,
105
+ s->unknown_header_fields, 0);
106
if (ret < 0) {
107
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
108
"fields");
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
110
ret = -ENOMEM;
171
goto fail;
111
goto fail;
172
}
112
}
173
ret = bdrv_pread(bs->file, header.backing_file_offset,
113
- ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
174
- bs->backing_file, len);
114
- s->l1_table, 0);
175
+ bs->auto_backing_file, len);
115
+ ret = bdrv_co_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
116
+ s->l1_table, 0);
117
if (ret < 0) {
118
error_setg_errno(errp, -ret, "Could not read L1 table");
119
goto fail;
120
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
121
}
122
123
s->image_backing_file = g_malloc(len + 1);
124
- ret = bdrv_pread(bs->file, header.backing_file_offset, len,
125
- s->image_backing_file, 0);
126
+ ret = bdrv_co_pread(bs->file, header.backing_file_offset, len,
127
+ s->image_backing_file, 0);
176
if (ret < 0) {
128
if (ret < 0) {
177
error_setg_errno(errp, -ret, "Could not read backing file name");
129
error_setg_errno(errp, -ret, "Could not read backing file name");
178
goto fail;
130
goto fail;
179
}
131
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
180
- bs->backing_file[len] = '\0';
132
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
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
}
133
}
187
134
188
/* Internal snapshots */
135
- ret = blk_pwrite(blk, 0, cluster_size, header, 0);
189
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
136
+ ret = blk_co_pwrite(blk, 0, cluster_size, header, 0);
190
return -EINVAL;
137
g_free(header);
138
if (ret < 0) {
139
error_setg_errno(errp, -ret, "Could not write qcow2 header");
140
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
141
/* Write a refcount table with one refcount block */
142
refcount_table = g_malloc0(2 * cluster_size);
143
refcount_table[0] = cpu_to_be64(2 * cluster_size);
144
- ret = blk_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
145
+ ret = blk_co_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
146
g_free(refcount_table);
147
148
if (ret < 0) {
149
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
191
}
150
}
192
151
193
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
152
/* Okay, now that we have a valid image, let's give it the right size */
194
+ backing_file ?: "");
153
- ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
195
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
154
- 0, errp);
196
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
155
+ ret = blk_co_truncate(blk, qcow2_opts->size, false,
197
156
+ qcow2_opts->preallocation, 0, errp);
198
diff --git a/block/qed.c b/block/qed.c
157
if (ret < 0) {
199
index XXXXXXX..XXXXXXX 100644
158
error_prepend(errp, "Could not resize image: ");
200
--- a/block/qed.c
159
goto out;
201
+++ b/block/qed.c
202
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
203
}
204
205
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
206
- s->header.backing_filename_size, bs->backing_file,
207
- sizeof(bs->backing_file));
208
+ s->header.backing_filename_size,
209
+ bs->auto_backing_file,
210
+ sizeof(bs->auto_backing_file));
211
if (ret < 0) {
212
return ret;
213
}
214
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
215
+ bs->auto_backing_file);
216
217
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
218
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
219
diff --git a/block/vmdk.c b/block/vmdk.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/block/vmdk.c
222
+++ b/block/vmdk.c
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
224
ret = -EINVAL;
225
goto out;
226
}
227
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
228
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
229
ret = -EINVAL;
230
goto out;
231
}
232
233
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
234
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
235
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
236
+ bs->auto_backing_file);
237
}
238
239
out:
240
--
160
--
241
2.20.1
161
2.37.3
242
243
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Error reporting for user_creatable_add_opts_foreach was changed so that
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
it no longer called 'error_report_err' in:
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
5
Message-Id: <20221013123711.620631-21-pbonzini@redhat.com>
6
commit 7e1e0c11127bde81cff260fc6859690435c509d6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
8
---
22
qemu-img.c | 26 +++++++++++++-------------
9
block/qed-table.c | 2 +-
23
1 file changed, 13 insertions(+), 13 deletions(-)
10
block/qed.c | 12 ++++++------
11
2 files changed, 7 insertions(+), 7 deletions(-)
24
12
25
diff --git a/qemu-img.c b/qemu-img.c
13
diff --git a/block/qed-table.c b/block/qed-table.c
26
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
15
--- a/block/qed-table.c
28
+++ b/qemu-img.c
16
+++ b/block/qed-table.c
29
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
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
}
18
}
37
19
38
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
20
if (flush) {
39
21
- ret = bdrv_flush(s->bs);
40
if (qemu_opts_foreach(&qemu_object_opts,
22
+ ret = bdrv_co_flush(s->bs);
41
user_creatable_add_opts_foreach,
23
if (ret < 0) {
42
- NULL, NULL)) {
24
goto out;
43
+ NULL, &error_fatal)) {
25
}
44
return 1;
26
diff --git a/block/qed.c b/block/qed.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/qed.c
29
+++ b/block/qed.c
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
31
int64_t file_size;
32
int ret;
33
34
- ret = bdrv_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
35
+ ret = bdrv_co_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
36
if (ret < 0) {
37
error_setg(errp, "Failed to read QED header");
38
return ret;
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
40
}
41
42
/* From here on only known autoclear feature bits are valid */
43
- bdrv_flush(bs->file->bs);
44
+ bdrv_co_flush(bs->file->bs);
45
}
45
}
46
46
47
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
47
s->l1_table = qed_alloc_table(s);
48
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
49
if (qemu_opts_foreach(&qemu_object_opts,
49
* The QED format associates file length with allocation status,
50
user_creatable_add_opts_foreach,
50
* so a new file (which is empty) must have a length of 0.
51
- NULL, NULL)) {
51
*/
52
+ NULL, &error_fatal)) {
52
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
53
return 1;
53
+ ret = blk_co_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
54
}
54
if (ret < 0) {
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;
55
goto out;
136
}
56
}
137
@@ -XXX,XX +XXX,XX @@ static int img_measure(int argc, char **argv)
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
138
58
}
139
if (qemu_opts_foreach(&qemu_object_opts,
59
140
user_creatable_add_opts_foreach,
60
qed_header_cpu_to_le(&header, &le_header);
141
- NULL, NULL)) {
61
- ret = blk_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
142
+ NULL, &error_fatal)) {
62
+ ret = blk_co_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
63
if (ret < 0) {
143
goto out;
64
goto out;
144
}
65
}
145
66
- ret = blk_pwrite(blk, sizeof(le_header), header.backing_filename_size,
67
+ ret = blk_co_pwrite(blk, sizeof(le_header), header.backing_filename_size,
68
qed_opts->backing_file, 0);
69
if (ret < 0) {
70
goto out;
71
}
72
73
l1_table = g_malloc0(l1_size);
74
- ret = blk_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
75
+ ret = blk_co_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
76
if (ret < 0) {
77
goto out;
78
}
146
--
79
--
147
2.20.1
80
2.37.3
148
149
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Both of the defaults we currently have in the curl driver are named
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
based on a slightly different schema, let's unify that and call both
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
CURL_BLOCK_OPT_${NAME}_DEFAULT.
5
Message-Id: <20221013123711.620631-22-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vdi.c | 17 +++++++++--------
10
1 file changed, 9 insertions(+), 8 deletions(-)
6
11
7
While at it, we can add a macro for the third option for which a default
12
diff --git a/block/vdi.c b/block/vdi.c
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
13
index XXXXXXX..XXXXXXX 100644
20
--- a/block/curl.c
14
--- a/block/vdi.c
21
+++ b/block/curl.c
15
+++ b/block/vdi.c
22
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
16
@@ -XXX,XX +XXX,XX @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
23
17
* so this full-cluster write does not overlap a partial write
24
#define CURL_NUM_STATES 8
18
* of the same cluster, issued from the "else" branch.
25
#define CURL_NUM_ACB 8
19
*/
26
-#define READ_AHEAD_DEFAULT (256 * 1024)
20
- ret = bdrv_pwrite(bs->file, data_offset, s->block_size, block, 0);
27
-#define CURL_TIMEOUT_DEFAULT 5
21
+ ret = bdrv_co_pwrite(bs->file, data_offset, s->block_size, block,
28
#define CURL_TIMEOUT_MAX 10000
22
+ 0);
29
23
qemu_co_rwlock_unlock(&s->bmap_lock);
30
#define CURL_BLOCK_OPT_URL "url"
24
} else {
31
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
25
nonallocating_write:
32
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
26
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
33
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
27
assert(VDI_IS_ALLOCATED(bmap_first));
34
28
*header = s->header;
35
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
29
vdi_header_to_le(header);
36
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
30
- ret = bdrv_pwrite(bs->file, 0, sizeof(*header), header, 0);
37
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
31
+ ret = bdrv_co_pwrite(bs->file, 0, sizeof(*header), header, 0);
38
+
32
g_free(header);
39
struct BDRVCURLState;
33
40
34
if (ret < 0) {
41
static bool libcurl_initialized;
35
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
42
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
36
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
37
logout("will write %u block map sectors starting from entry %u\n",
38
n_sectors, bmap_first);
39
- ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE,
40
- n_sectors * SECTOR_SIZE, base, 0);
41
+ ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE,
42
+ n_sectors * SECTOR_SIZE, base, 0);
43
}
43
}
44
44
45
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
45
return ret;
46
- READ_AHEAD_DEFAULT);
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
47
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
47
vdi_header_print(&header);
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
}
48
}
53
49
vdi_header_to_le(&header);
54
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
50
- ret = blk_pwrite(blk, offset, sizeof(header), &header, 0);
55
- CURL_TIMEOUT_DEFAULT);
51
+ ret = blk_co_pwrite(blk, offset, sizeof(header), &header, 0);
56
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
52
if (ret < 0) {
57
if (s->timeout > CURL_TIMEOUT_MAX) {
53
error_setg(errp, "Error writing header");
58
error_setg(errp, "timeout parameter is too large or negative");
54
goto exit;
59
goto out_noclean;
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
56
bmap[i] = VDI_UNALLOCATED;
57
}
58
}
59
- ret = blk_pwrite(blk, offset, bmap_size, bmap, 0);
60
+ ret = blk_co_pwrite(blk, offset, bmap_size, bmap, 0);
61
if (ret < 0) {
62
error_setg(errp, "Error writing bmap");
63
goto exit;
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
60
}
65
}
61
66
62
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
67
if (image_type == VDI_TYPE_STATIC) {
63
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
68
- ret = blk_truncate(blk, offset + blocks * block_size, false,
64
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
69
- PREALLOC_MODE_OFF, 0, errp);
65
70
+ ret = blk_co_truncate(blk, offset + blocks * block_size, false,
66
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
71
+ PREALLOC_MODE_OFF, 0, errp);
67
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
72
if (ret < 0) {
73
error_prepend(errp, "Failed to statically allocate file");
74
goto exit;
68
--
75
--
69
2.20.1
76
2.37.3
70
71
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
In qcow2_snapshot_create there is the following code block:
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
/* Generate an ID */
5
Message-Id: <20221013123711.620631-23-pbonzini@redhat.com>
6
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
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>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
59
---
8
---
60
block/qcow2-snapshot.c | 5 -----
9
block/vhdx.c | 8 ++++----
61
1 file changed, 5 deletions(-)
10
1 file changed, 4 insertions(+), 4 deletions(-)
62
11
63
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
12
diff --git a/block/vhdx.c b/block/vhdx.c
64
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
65
--- a/block/qcow2-snapshot.c
14
--- a/block/vhdx.c
66
+++ b/block/qcow2-snapshot.c
15
+++ b/block/vhdx.c
67
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
68
/* Generate an ID */
17
creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
69
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
18
&creator_items, NULL);
70
19
signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
71
- /* Check that the ID is unique */
20
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
72
- if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
21
- 0);
73
- return -EEXIST;
22
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
74
- }
23
+ 0);
75
-
24
if (ret < 0) {
76
/* Populate sn with passed data */
25
error_setg_errno(errp, -ret, "Failed to write file signature");
77
sn->id_str = g_strdup(sn_info->id_str);
26
goto delete_and_exit;
78
sn->name = g_strdup(sn_info->name);
27
}
28
if (creator) {
29
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
30
- creator_items * sizeof(gunichar2), creator, 0);
31
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
32
+ creator_items * sizeof(gunichar2), creator, 0);
33
if (ret < 0) {
34
error_setg_errno(errp, -ret, "Failed to write creator field");
35
goto delete_and_exit;
79
--
36
--
80
2.20.1
37
2.37.3
81
82
diff view generated by jsdifflib
1
From: yuchenlin <yuchenlin@synology.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
In vmdk_co_create_opts, when it finds hw_version is undefined, it will
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
set it to 4, which misleading the compat6 and hwversion in
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
vmdk_co_do_create. Simply set hw_version to NULL after free, let
5
Message-Id: <20221013123711.620631-24-pbonzini@redhat.com>
6
the logic in vmdk_co_do_create to decide the value of hw_version.
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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
---
8
---
20
block/vmdk.c | 2 +-
9
block/vmdk.c | 54 ++++++++++++++++++++++++++--------------------------
21
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 27 insertions(+), 27 deletions(-)
22
11
23
diff --git a/block/vmdk.c b/block/vmdk.c
12
diff --git a/block/vmdk.c b/block/vmdk.c
24
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
25
--- a/block/vmdk.c
14
--- a/block/vmdk.c
26
+++ b/block/vmdk.c
15
+++ b/block/vmdk.c
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
28
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
17
if (copy_from_backing) {
29
if (strcmp(hw_version, "undefined") == 0) {
18
/* qcow2 emits this on bs->file instead of bs->backing */
30
g_free(hw_version);
19
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
31
- hw_version = g_strdup("4");
20
- ret = bdrv_pread(bs->backing, offset, skip_start_bytes,
32
+ hw_version = NULL;
21
- whole_grain, 0);
22
+ ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes,
23
+ whole_grain, 0);
24
if (ret < 0) {
25
ret = VMDK_ERROR;
26
goto exit;
27
}
28
}
29
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
30
- ret = bdrv_pwrite(extent->file, cluster_offset, skip_start_bytes,
31
- whole_grain, 0);
32
+ ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes,
33
+ whole_grain, 0);
34
if (ret < 0) {
35
ret = VMDK_ERROR;
36
goto exit;
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
38
if (copy_from_backing) {
39
/* qcow2 emits this on bs->file instead of bs->backing */
40
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
41
- ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
42
- cluster_bytes - skip_end_bytes,
43
- whole_grain + skip_end_bytes, 0);
44
+ ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes,
45
+ cluster_bytes - skip_end_bytes,
46
+ whole_grain + skip_end_bytes, 0);
47
if (ret < 0) {
48
ret = VMDK_ERROR;
49
goto exit;
50
}
51
}
52
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
53
- ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
54
- cluster_bytes - skip_end_bytes,
55
- whole_grain + skip_end_bytes, 0);
56
+ ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes,
57
+ cluster_bytes - skip_end_bytes,
58
+ whole_grain + skip_end_bytes, 0);
59
if (ret < 0) {
60
ret = VMDK_ERROR;
61
goto exit;
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
63
offset = cpu_to_le32(offset);
64
/* update L2 table */
65
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
66
- if (bdrv_pwrite(extent->file,
67
- ((int64_t)m_data->l2_offset * 512)
68
- + (m_data->l2_index * sizeof(offset)),
69
- sizeof(offset), &offset, 0) < 0) {
70
+ if (bdrv_co_pwrite(extent->file,
71
+ ((int64_t)m_data->l2_offset * 512)
72
+ + (m_data->l2_index * sizeof(offset)),
73
+ sizeof(offset), &offset, 0) < 0) {
74
return VMDK_ERROR;
33
}
75
}
34
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
76
/* update backup L2 table */
35
zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
77
if (extent->l1_backup_table_offset != 0) {
78
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
79
- if (bdrv_pwrite(extent->file,
80
- ((int64_t)m_data->l2_offset * 512)
81
- + (m_data->l2_index * sizeof(offset)),
82
- sizeof(offset), &offset, 0) < 0) {
83
+ if (bdrv_co_pwrite(extent->file,
84
+ ((int64_t)m_data->l2_offset * 512)
85
+ + (m_data->l2_index * sizeof(offset)),
86
+ sizeof(offset), &offset, 0) < 0) {
87
return VMDK_ERROR;
88
}
89
}
90
- if (bdrv_flush(extent->file->bs) < 0) {
91
+ if (bdrv_co_flush(extent->file->bs) < 0) {
92
return VMDK_ERROR;
93
}
94
if (m_data->l2_cache_entry) {
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
96
}
97
l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
98
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
99
- if (bdrv_pread(extent->file,
100
+ if (bdrv_co_pread(extent->file,
101
(int64_t)l2_offset * 512,
102
l2_size_bytes,
103
- l2_table,
104
- 0
105
+ l2_table, 0
106
) < 0) {
107
return VMDK_ERROR;
108
}
109
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
110
cluster_buf = g_malloc(buf_bytes);
111
uncomp_buf = g_malloc(cluster_bytes);
112
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
113
- ret = bdrv_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, 0);
114
+ ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf,
115
+ 0);
116
if (ret < 0) {
117
goto out;
118
}
119
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
120
return length;
121
}
122
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
123
- ret = bdrv_truncate(s->extents[i].file, length, false,
124
- PREALLOC_MODE_OFF, 0, NULL);
125
+ ret = bdrv_co_truncate(s->extents[i].file, length, false,
126
+ PREALLOC_MODE_OFF, 0, NULL);
127
if (ret < 0) {
128
return ret;
129
}
130
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
131
desc_offset = 0x200;
132
}
133
134
- ret = blk_pwrite(blk, desc_offset, desc_len, desc, 0);
135
+ ret = blk_co_pwrite(blk, desc_offset, desc_len, desc, 0);
136
if (ret < 0) {
137
error_setg_errno(errp, -ret, "Could not write description");
138
goto exit;
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
140
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
141
* for description file */
142
if (desc_offset == 0) {
143
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
144
+ ret = blk_co_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
145
if (ret < 0) {
146
goto exit;
147
}
36
--
148
--
37
2.20.1
149
2.37.3
38
39
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
math.ceil() returns an integer on Python 3.x, but a float on Python 2.x.
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
range() always needs integers, so we need an explicit conversion on 2.x
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
(which does not hurt on 3.x).
5
Message-Id: <20221013123711.620631-25-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
It is not quite clear whether we want to support Python 2.x for any
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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
---
8
---
17
tests/qemu-iotests/237 | 2 +-
9
blockdev.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
19
11
20
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
12
diff --git a/blockdev.c b/blockdev.c
21
index XXXXXXX..XXXXXXX 100755
13
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/237
14
--- a/blockdev.c
23
+++ b/tests/qemu-iotests/237
15
+++ b/blockdev.c
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
16
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(bool has_device, const char *device,
25
iotests.log("= %s %d =" % (subfmt, size))
17
bdrv_co_unlock(bs);
26
iotests.log("")
18
27
19
old_ctx = bdrv_co_enter(bs);
28
- num_extents = math.ceil(size / 2.0**31)
20
- blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
29
+ num_extents = int(math.ceil(size / 2.0**31))
21
+ blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
30
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
22
bdrv_co_leave(bs, old_ctx);
31
23
32
vm.launch()
24
bdrv_co_lock(bs);
33
--
25
--
34
2.20.1
26
2.37.3
35
36
diff view generated by jsdifflib
1
For some users of BlockBackends, just increasing the in_flight counter
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
is easier than implementing separate handlers in BlockDevOps. Make the
3
helper functions for this public.
4
2
3
blk_set_enable_write_cache() is defined as GLOBAL_STATE_CODE
4
but can be invoked from iothreads when handling scsi requests.
5
This triggers an assertion failure:
6
7
0x00007fd6c3515ce1 in raise () from /lib/x86_64-linux-gnu/libc.so.6
8
0x00007fd6c34ff537 in abort () from /lib/x86_64-linux-gnu/libc.so.6
9
0x00007fd6c34ff40f in ?? () from /lib/x86_64-linux-gnu/libc.so.6
10
0x00007fd6c350e662 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
11
0x000056149e2cea03 in blk_set_enable_write_cache (wce=true, blk=0x5614a01c27f0)
12
at ../src/block/block-backend.c:1949
13
0x000056149e2d0a67 in blk_set_enable_write_cache (blk=0x5614a01c27f0,
14
wce=<optimized out>) at ../src/block/block-backend.c:1951
15
0x000056149dfe9c59 in scsi_disk_apply_mode_select (p=0x7fd6b400c00e "\004",
16
page=<optimized out>, s=<optimized out>) at ../src/hw/scsi/scsi-disk.c:1520
17
mode_select_pages (change=true, len=18, p=0x7fd6b400c00e "\004", r=0x7fd6b4001ff0)
18
at ../src/hw/scsi/scsi-disk.c:1570
19
scsi_disk_emulate_mode_select (inbuf=<optimized out>, r=0x7fd6b4001ff0) at
20
../src/hw/scsi/scsi-disk.c:1640
21
scsi_disk_emulate_write_data (req=0x7fd6b4001ff0) at ../src/hw/scsi/scsi-disk.c:1934
22
0x000056149e18ff16 in virtio_scsi_handle_cmd_req_submit (req=<optimized out>,
23
req=<optimized out>, s=0x5614a12f16b0) at ../src/hw/scsi/virtio-scsi.c:719
24
virtio_scsi_handle_cmd_vq (vq=0x7fd6bab92140, s=0x5614a12f16b0) at
25
../src/hw/scsi/virtio-scsi.c:761
26
virtio_scsi_handle_cmd (vq=<optimized out>, vdev=<optimized out>) at
27
../src/hw/scsi/virtio-scsi.c:775
28
virtio_scsi_handle_cmd (vdev=0x5614a12f16b0, vq=0x7fd6bab92140) at
29
../src/hw/scsi/virtio-scsi.c:765
30
0x000056149e1a8aa6 in virtio_queue_notify_vq (vq=0x7fd6bab92140) at
31
../src/hw/virtio/virtio.c:2365
32
0x000056149e3ccea5 in aio_dispatch_handler (ctx=ctx@entry=0x5614a01babe0,
33
node=<optimized out>) at ../src/util/aio-posix.c:369
34
0x000056149e3cd868 in aio_dispatch_ready_handlers (ready_list=0x7fd6c09b2680,
35
ctx=0x5614a01babe0) at ../src/util/aio-posix.c:399
36
aio_poll (ctx=0x5614a01babe0, blocking=blocking@entry=true) at
37
../src/util/aio-posix.c:713
38
0x000056149e2a7796 in iothread_run (opaque=opaque@entry=0x56149ffde500) at
39
../src/iothread.c:67
40
0x000056149e3d0859 in qemu_thread_start (args=0x7fd6c09b26f0) at
41
../src/util/qemu-thread-posix.c:504
42
0x00007fd6c36b9ea7 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
43
0x00007fd6c35d9aef in clone () from /lib/x86_64-linux-gnu/libc.so.6
44
45
Changing GLOBAL_STATE_CODE in IO_CODE is allowed, since GSC callers are
46
allowed to call IO_CODE.
47
48
Resolves: #1272
49
50
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
51
Message-Id: <20221027072726.2681500-1-eesposit@redhat.com>
52
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
53
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
54
Tested-by: Antoine Damhet <antoine.damhet@shadow.tech>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
55
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
56
---
7
include/sysemu/block-backend.h | 2 ++
57
block/block-backend.c | 2 +-
8
block/block-backend.c | 4 ++--
58
1 file changed, 1 insertion(+), 1 deletion(-)
9
2 files changed, 4 insertions(+), 2 deletions(-)
10
59
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
60
diff --git a/block/block-backend.c b/block/block-backend.c
25
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
26
--- a/block/block-backend.c
62
--- a/block/block-backend.c
27
+++ b/block/block-backend.c
63
+++ b/block/block-backend.c
28
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
64
@@ -XXX,XX +XXX,XX @@ bool blk_enable_write_cache(BlockBackend *blk)
29
return bdrv_make_zero(blk->root, flags);
65
66
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
67
{
68
- GLOBAL_STATE_CODE();
69
+ IO_CODE();
70
blk->enable_write_cache = wce;
30
}
71
}
31
72
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
--
73
--
44
2.20.1
74
2.37.3
45
46
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
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: Max Reitz <mreitz@redhat.com>
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-7-mreitz@redhat.com
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/iotests.py | 10 ++++++++++
9
1 file changed, 10 insertions(+)
10
11
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/iotests.py
14
+++ b/tests/qemu-iotests/iotests.py
15
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
16
lines.append(line)
17
return '\n'.join(lines)
18
19
+def filter_imgfmt(msg):
20
+ return msg.replace(imgfmt, 'IMGFMT')
21
+
22
+def filter_qmp_imgfmt(qmsg):
23
+ def _filter(key, value):
24
+ if is_str(value):
25
+ return filter_imgfmt(value)
26
+ return value
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
2.20.1
34
35
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
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
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
Signed-off-by: Max Reitz <mreitz@redhat.com>
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
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/224
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python
21
+#
22
+# Test json:{} filenames with qemu-internal BDSs
23
+# (the one of commit, to be precise)
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, qemu_io_silent, filter_qmp_testfiles, \
44
+ filter_qmp_imgfmt
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'])
50
+
51
+
52
+# There are two variations of this test:
53
+# (1) We do not set filter_node_name. In that case, the commit_top
54
+# driver should not appear anywhere.
55
+# (2) We do set filter_node_name. In that case, it should appear.
56
+#
57
+# This for loop executes both.
58
+for filter_node_name in False, True:
59
+ log('')
60
+ log('--- filter_node_name: %s ---' % filter_node_name)
61
+ log('')
62
+
63
+ with iotests.FilePath('base.img') as base_img_path, \
64
+ iotests.FilePath('mid.img') as mid_img_path, \
65
+ iotests.FilePath('top.img') as top_img_path, \
66
+ iotests.VM() as vm:
67
+
68
+ assert qemu_img('create', '-f', iotests.imgfmt,
69
+ base_img_path, '64M') == 0
70
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
71
+ mid_img_path) == 0
72
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
73
+ top_img_path) == 0
74
+
75
+ # Something to commit
76
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
77
+
78
+ vm.launch()
79
+
80
+ # Change the bottom-most image's backing file (to null-co://)
81
+ # to enforce json:{} filenames
82
+ vm.qmp_log('blockdev-add',
83
+ node_name='top',
84
+ driver=iotests.imgfmt,
85
+ file={
86
+ 'driver': 'file',
87
+ 'filename': top_img_path
88
+ },
89
+ backing={
90
+ 'node-name': 'mid',
91
+ 'driver': iotests.imgfmt,
92
+ 'file': {
93
+ 'driver': 'file',
94
+ 'filename': mid_img_path
95
+ },
96
+ 'backing': {
97
+ 'node-name': 'base',
98
+ 'driver': iotests.imgfmt,
99
+ 'file': {
100
+ 'driver': 'file',
101
+ 'filename': base_img_path
102
+ },
103
+ 'backing': {
104
+ 'driver': 'null-co'
105
+ }
106
+ }
107
+ },
108
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
109
+
110
+ # As long as block-commit does not accept node names, we have to
111
+ # get our mid/base filenames here
112
+ mid_name = vm.node_info('mid')['image']['filename']
113
+ base_name = vm.node_info('base')['image']['filename']
114
+
115
+ assert mid_name[:5] == 'json:'
116
+ assert base_name[:5] == 'json:'
117
+
118
+ # Start the block job
119
+ if filter_node_name:
120
+ vm.qmp_log('block-commit',
121
+ job_id='commit',
122
+ device='top',
123
+ filter_node_name='filter_node',
124
+ top=mid_name,
125
+ base=base_name,
126
+ speed=1,
127
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
128
+ else:
129
+ vm.qmp_log('block-commit',
130
+ job_id='commit',
131
+ device='top',
132
+ top=mid_name,
133
+ base=base_name,
134
+ speed=1,
135
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
136
+
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
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/tests/qemu-iotests/224.out
164
@@ -XXX,XX +XXX,XX @@
165
+
166
+--- filter_node_name: False ---
167
+
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"}}
169
+{"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\"}}"}}
171
+{"return": {}}
172
+{"execute": "job-pause", "arguments": {"id": "commit"}}
173
+{"return": {}}
174
+
175
+--- filter_node_name: True ---
176
+
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"}}
178
+{"return": {}}
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\"}}"}}
180
+{"return": {}}
181
+{"execute": "job-pause", "arguments": {"id": "commit"}}
182
+{"return": {}}
183
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
184
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qemu-iotests/group
186
+++ b/tests/qemu-iotests/group
187
@@ -XXX,XX +XXX,XX @@
188
221 rw auto quick
189
222 rw auto quick
190
223 rw auto quick
191
+224 rw auto quick
192
225 rw auto quick
193
226 auto quick
194
227 auto quick
195
--
196
2.20.1
197
198
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
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