1
The following changes since commit 59a568b57848b10e8a44518a889323f12ccdd8f4:
1
The following changes since commit 013a18edbbc59cdad019100c7d03c0494642b74c:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190222-pull-request' into staging (2019-02-25 12:49:07 +0000)
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200514' into staging (2020-05-14 16:17:55 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1b967e9f348d48788a2ab481d45398b80ce71fa6:
9
for you to fetch changes up to 7d8f21a650e562270f5ed5341134c9c2c39dc5e8:
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
iotests/030: Reduce run time by unthrottling job earlier (2020-05-15 14:12:34 +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
- Introduce real BdrvChildRole
17
- bdrv_set_aio_context() related fixes
17
- blk/bdrv_make_empty() functions instead of calling callbacks directly
18
- HMP snapshot commands: Use only tag, not the ID to identify snapshots
18
- mirror: Make sure that source and target size match
19
- qmeu-img, commit: Error path fixes
19
- block-copy: Fix uninitialized variable
20
- block/nvme: Build fix for gcc 9
20
- block/replication: Avoid cancelling the job twice
21
- MAINTAINERS updates
21
- ahci: Log lost IRQs
22
- Fix various issues with bdrv_refresh_filename()
22
- iotests: Run pylint and mypy in a testcase
23
- Fix various iotests
23
- iotests: log messages from notrun()
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
John Snow (1):
29
commit: Replace commit_top_bs on failure after deleting the block job
27
iotests: log messages from notrun()
30
qcow2: Assert that L2 table offsets fit in the L1 table
31
28
32
Daniel Henrique Barboza (3):
29
Kevin Wolf (8):
33
block/snapshot.c: eliminate use of ID input in snapshot operations
30
iotests/109: Don't mirror with mismatched size
34
block/snapshot: remove bdrv_snapshot_delete_by_id_or_name
31
iotests/229: Use blkdebug to inject an error
35
qcow2-snapshot: remove redundant find_snapshot_by_id_and_name call
32
mirror: Make sure that source and target size match
33
iotests: Mirror with different source/target size
34
iotests: Fix incomplete type declarations
35
iotests: Run pylint and mypy in a testcase
36
replication: Avoid blk_make_empty() on read-only child
37
iotests/030: Reduce run time by unthrottling job earlier
36
38
37
Daniel P. Berrangé (1):
39
Lukas Straub (1):
38
qemu-img: fix error reporting for -object
40
block/replication.c: Avoid cancelling the job twice
39
41
40
Denis Plotnikov (1):
42
Max Reitz (38):
41
block: don't set the same context
43
block: Add bdrv_make_empty()
44
block: Add blk_make_empty()
45
block: Use blk_make_empty() after commits
46
block: Use bdrv_make_empty() where possible
47
block: Mark commit, mirror, blkreplay as filters
48
block: Add BlockDriver.is_format
49
block: Rename BdrvChildRole to BdrvChildClass
50
block: Add BdrvChildRole and BdrvChildRoleBits
51
block: Add BdrvChildRole to BdrvChild
52
block: Pass BdrvChildRole to bdrv_child_perm()
53
block: Pass BdrvChildRole to .inherit_options()
54
block: Pass parent_is_format to .inherit_options()
55
block: Rename bdrv_inherited_options()
56
block: Add generic bdrv_inherited_options()
57
block: Use bdrv_inherited_options()
58
block: Unify bdrv_child_cb_attach()
59
block: Unify bdrv_child_cb_detach()
60
block: Add child_of_bds
61
block: Distinguish paths in *_format_default_perms
62
block: Pull out bdrv_default_perms_for_cow()
63
block: Pull out bdrv_default_perms_for_storage()
64
block: Relax *perms_for_storage for data children
65
block: Add bdrv_default_perms()
66
raw-format: Split raw_read_options()
67
block: Switch child_format users to child_of_bds
68
block: Drop child_format
69
block: Make backing files child_of_bds children
70
block: Drop child_backing
71
block: Make format drivers use child_of_bds
72
block: Make filter drivers use child_of_bds
73
block: Use child_of_bds in remaining places
74
tests: Use child_of_bds instead of child_file
75
block: Use bdrv_default_perms()
76
block: Make bdrv_filter_default_perms() static
77
block: Drop bdrv_format_default_perms()
78
block: Drop child_file
79
block: Pass BdrvChildRole in remaining cases
80
block: Drop @child_class from bdrv_child_perm()
42
81
43
Jeff Cody (2):
82
Philippe Mathieu-Daudé (3):
44
MAINTAINERS: Replace myself with John Snow for block jobs
83
block/block-copy: Fix uninitialized variable in block_copy_task_entry
45
MAINTAINERS: Remove myself as block maintainer
84
block/block-copy: Simplify block_copy_do_copy()
85
hw/ide/ahci: Log lost IRQs
46
86
47
Kevin Wolf (14):
87
include/block/block.h | 65 ++++-
48
block-backend: Make blk_inc/dec_in_flight public
88
include/block/block_int.h | 57 ++--
49
virtio-blk: Increase in_flight for request restart BH
89
include/sysemu/block-backend.h | 2 +
50
nbd: Restrict connection_co reentrance
90
block.c | 601 ++++++++++++++++++++++++---------------
51
io: Make qio_channel_yield() interruptible
91
block/backup-top.c | 11 +-
52
io: Remove redundant read/write_coroutine assignments
92
block/blkdebug.c | 10 +-
53
nbd: Move nbd_read_eof() to nbd/client.c
93
block/blklogwrites.c | 16 +-
54
nbd: Use low-level QIOChannel API in nbd_read_eof()
94
block/blkreplay.c | 8 +-
55
nbd: Increase bs->in_flight during AioContext switch
95
block/blkverify.c | 10 +-
56
block: Don't poll in bdrv_set_aio_context()
96
block/block-backend.c | 30 +-
57
block: Fix AioContext switch for drained node
97
block/block-copy.c | 14 +-
58
test-bdrv-drain: AioContext switch in drained section
98
block/bochs.c | 7 +-
59
block: Use normal drain for bdrv_set_aio_context()
99
block/cloop.c | 7 +-
60
aio-posix: Assert that aio_poll() is always called in home thread
100
block/commit.c | 20 +-
61
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block
101
block/copy-on-read.c | 7 +-
102
block/crypto.c | 8 +-
103
block/dmg.c | 7 +-
104
block/filter-compress.c | 7 +-
105
block/io.c | 22 +-
106
block/mirror.c | 25 +-
107
block/parallels.c | 7 +-
108
block/qcow.c | 7 +-
109
block/qcow2.c | 20 +-
110
block/qed.c | 7 +-
111
block/quorum.c | 8 +-
112
block/raw-format.c | 128 +++++----
113
block/replication.c | 23 +-
114
block/throttle.c | 7 +-
115
block/vdi.c | 7 +-
116
block/vhdx.c | 7 +-
117
block/vmdk.c | 23 +-
118
block/vpc.c | 7 +-
119
block/vvfat.c | 17 +-
120
blockjob.c | 7 +-
121
hw/ide/ahci.c | 1 +
122
qemu-img.c | 19 +-
123
tests/test-bdrv-drain.c | 72 +++--
124
tests/test-bdrv-graph-mod.c | 10 +-
125
tests/test-block-iothread.c | 17 +-
126
tests/qemu-iotests/iotests.py | 19 +-
127
tests/qemu-iotests/030 | 6 +-
128
tests/qemu-iotests/041 | 45 +++
129
tests/qemu-iotests/041.out | 4 +-
130
tests/qemu-iotests/098.out | 8 +-
131
tests/qemu-iotests/109 | 10 +-
132
tests/qemu-iotests/109.out | 74 ++---
133
tests/qemu-iotests/229 | 15 +-
134
tests/qemu-iotests/229.out | 6 +-
135
tests/qemu-iotests/297 | 44 +++
136
tests/qemu-iotests/297.out | 3 +
137
tests/qemu-iotests/common.filter | 5 +
138
tests/qemu-iotests/group | 1 +
139
52 files changed, 995 insertions(+), 573 deletions(-)
140
create mode 100755 tests/qemu-iotests/297
141
create mode 100644 tests/qemu-iotests/297.out
62
142
63
Max Reitz (42):
64
block: Use bdrv_refresh_filename() to pull
65
block: Use children list in bdrv_refresh_filename
66
block: Skip implicit nodes for filename info
67
block: Add BDS.auto_backing_file
68
block: Respect backing bs in bdrv_refresh_filename
69
iotests.py: Add filter_imgfmt()
70
iotests.py: Add node_info()
71
iotests: Add test for backing file overrides
72
block: Make path_combine() return the path
73
block: bdrv_get_full_backing_filename_from_...'s ret. val.
74
block: bdrv_get_full_backing_filename's ret. val.
75
block: Add bdrv_make_absolute_filename()
76
block: Fix bdrv_find_backing_image()
77
block: Add bdrv_dirname()
78
blkverify: Make bdrv_dirname() return NULL
79
quorum: Make bdrv_dirname() return NULL
80
block/nbd: Make bdrv_dirname() return NULL
81
block/nfs: Implement bdrv_dirname()
82
block: Use bdrv_dirname() for relative filenames
83
iotests: Add quorum case to test 110
84
block: Add strong_runtime_opts to BlockDriver
85
block: Add BlockDriver.bdrv_gather_child_options
86
block: Generically refresh runtime options
87
block: Purify .bdrv_refresh_filename()
88
block: Do not copy exact_filename from format file
89
block/nvme: Fix bdrv_refresh_filename()
90
block/curl: Harmonize option defaults
91
block/curl: Implement bdrv_refresh_filename()
92
block/null: Generate filename even with latency-ns
93
block: BDS options may lack the "driver" option
94
iotests: Test json:{} filenames of internal BDSs
95
iotests: Re-add filename filters
96
iotests: Fix 237 for Python 2.x
97
iotests: Remove superfluous rm from 232
98
iotests: Fix 232 for LUKS
99
iotests: Fix 207 to use QMP filters for qmp_log
100
iotests.py: Add is_str()
101
iotests.py: Filter filename in any string value
102
iotests: Filter SSH paths
103
iotests: Let 045 be run concurrently
104
iotests.py: s/_/-/g on keys in qmp_log()
105
iotests: Skip 211 on insufficient memory
106
143
107
Stefan Hajnoczi (2):
108
qcow2: include LUKS payload overhead in qemu-img measure
109
iotests: add LUKS payload overhead to 178 qemu-img measure test
110
111
Thomas Huth (1):
112
block/nvme: Remove QEMU_PACKED from naturally aligned NVMeRegs struct
113
114
Vladimir Sementsov-Ogievskiy (3):
115
block: improve should_update_child
116
block: fix bdrv_check_perm for non-tree subgraph
117
tests: add test-bdrv-graph-mod
118
119
yuchenlin (1):
120
vmdk: false positive of compat6 with hwversion not set
121
122
block/nbd-client.h | 1 +
123
include/block/block.h | 16 +-
124
include/block/block_int.h | 53 +++-
125
include/block/nbd.h | 3 +-
126
include/block/snapshot.h | 3 -
127
include/io/channel.h | 9 +-
128
include/sysemu/block-backend.h | 2 +
129
nbd/nbd-internal.h | 19 --
130
block.c | 597 +++++++++++++++++++++++++++------------
131
block/blkdebug.c | 70 ++---
132
block/blklogwrites.c | 33 +--
133
block/blkverify.c | 29 +-
134
block/block-backend.c | 4 +-
135
block/commit.c | 7 +-
136
block/crypto.c | 8 +
137
block/curl.c | 55 +++-
138
block/gluster.c | 19 ++
139
block/iscsi.c | 18 ++
140
block/mirror.c | 3 +-
141
block/nbd-client.c | 36 ++-
142
block/nbd.c | 46 +--
143
block/nfs.c | 54 ++--
144
block/null.c | 32 ++-
145
block/nvme.c | 29 +-
146
block/qapi.c | 16 +-
147
block/qcow.c | 14 +-
148
block/qcow2-cluster.c | 3 +
149
block/qcow2-snapshot.c | 5 -
150
block/qcow2.c | 89 +++++-
151
block/qed.c | 7 +-
152
block/quorum.c | 71 +++--
153
block/raw-format.c | 11 +-
154
block/rbd.c | 14 +
155
block/replication.c | 10 +-
156
block/sheepdog.c | 12 +
157
block/snapshot.c | 25 +-
158
block/ssh.c | 12 +
159
block/throttle.c | 7 +
160
block/vhdx-log.c | 1 +
161
block/vmdk.c | 46 ++-
162
block/vpc.c | 7 +
163
block/vvfat.c | 12 +
164
block/vxhs.c | 11 +
165
blockdev.c | 8 +
166
hw/block/virtio-blk.c | 4 +
167
io/channel.c | 22 +-
168
nbd/client.c | 52 +++-
169
qemu-img.c | 64 +++--
170
tests/test-bdrv-drain.c | 32 +++
171
tests/test-bdrv-graph-mod.c | 198 +++++++++++++
172
util/aio-posix.c | 3 +-
173
MAINTAINERS | 22 +-
174
hmp-commands.hx | 32 ++-
175
scripts/qemu.py | 5 +-
176
tests/Makefile.include | 2 +
177
tests/qemu-iotests/045 | 2 +-
178
tests/qemu-iotests/051.out | 8 +-
179
tests/qemu-iotests/051.pc.out | 8 +-
180
tests/qemu-iotests/110 | 29 +-
181
tests/qemu-iotests/110.out | 9 +-
182
tests/qemu-iotests/178 | 8 +
183
tests/qemu-iotests/178.out.qcow2 | 24 ++
184
tests/qemu-iotests/206.out | 56 ++--
185
tests/qemu-iotests/207 | 10 +-
186
tests/qemu-iotests/207.out | 18 +-
187
tests/qemu-iotests/210 | 5 +-
188
tests/qemu-iotests/210.out | 28 +-
189
tests/qemu-iotests/211 | 9 +-
190
tests/qemu-iotests/211.out | 26 +-
191
tests/qemu-iotests/212 | 5 +-
192
tests/qemu-iotests/212.out | 44 +--
193
tests/qemu-iotests/213 | 5 +-
194
tests/qemu-iotests/213.out | 46 +--
195
tests/qemu-iotests/224 | 139 +++++++++
196
tests/qemu-iotests/224.out | 18 ++
197
tests/qemu-iotests/228 | 239 ++++++++++++++++
198
tests/qemu-iotests/228.out | 84 ++++++
199
tests/qemu-iotests/232 | 5 +-
200
tests/qemu-iotests/237 | 7 +-
201
tests/qemu-iotests/237.out | 54 ++--
202
tests/qemu-iotests/common.rc | 1 +
203
tests/qemu-iotests/group | 2 +
204
tests/qemu-iotests/iotests.py | 36 ++-
205
83 files changed, 2191 insertions(+), 697 deletions(-)
206
create mode 100644 tests/test-bdrv-graph-mod.c
207
create mode 100755 tests/qemu-iotests/224
208
create mode 100644 tests/qemu-iotests/224.out
209
create mode 100755 tests/qemu-iotests/228
210
create mode 100644 tests/qemu-iotests/228.out
211
diff view generated by jsdifflib
Deleted patch
1
From: Jeff Cody <jcody@redhat.com>
2
1
3
I'll not be involved with day-to-day qemu development, and John
4
Snow is a block jobs wizard. Have him take over block job
5
maintainership duties.
6
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Acked-by: John Snow <jsnow@redhat.com>
9
Message-Id: <d56d7c6592e7d68aa72764e9616878394bffbc14.1537984851.git.jcody@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
MAINTAINERS | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: include/scsi/*
20
F: scsi/*
21
22
Block Jobs
23
-M: Jeff Cody <jcody@redhat.com>
24
+M: John Snow <jsnow@redhat.com>
25
L: qemu-block@nongnu.org
26
S: Supported
27
F: blockjob.c
28
@@ -XXX,XX +XXX,XX @@ F: block/commit.c
29
F: block/stream.c
30
F: block/mirror.c
31
F: qapi/job.json
32
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
33
+T: git https://github.com/jnsnow/qemu.git jobs
34
35
Block QAPI, monitor, command line
36
M: Markus Armbruster <armbru@redhat.com>
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
From: Jeff Cody <jcody@redhat.com>
2
1
3
I'll not be involved in day-to-day qemu development. Remove myself as
4
maintainer from the remainder of the network block drivers, and revert
5
them to the general block layer maintainership.
6
7
Move 'sheepdog' to the 'Odd Fixes' support level.
8
9
For VHDX, added my personal email address as a maintainer, as I can
10
answer questions or send the occassional bug fix. Leaving it as
11
'Supported', instead of 'Odd Fixes', because I think the rest of the
12
block layer maintainers and developers will upkeep it as well, if
13
needed.
14
15
Signed-off-by: Jeff Cody <jcody@redhat.com>
16
Acked-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <63e205cb84c8f0a10c1bc6d5d6856d72ceb56e41.1537984851.git.jcody@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
MAINTAINERS | 18 +++---------------
21
1 file changed, 3 insertions(+), 15 deletions(-)
22
23
diff --git a/MAINTAINERS b/MAINTAINERS
24
index XXXXXXX..XXXXXXX 100644
25
--- a/MAINTAINERS
26
+++ b/MAINTAINERS
27
@@ -XXX,XX +XXX,XX @@ F: block/vmdk.c
28
29
RBD
30
M: Josh Durgin <jdurgin@redhat.com>
31
-M: Jeff Cody <jcody@redhat.com>
32
L: qemu-block@nongnu.org
33
S: Supported
34
F: block/rbd.c
35
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
36
37
Sheepdog
38
M: Liu Yuan <namei.unix@gmail.com>
39
-M: Jeff Cody <jcody@redhat.com>
40
L: qemu-block@nongnu.org
41
-S: Supported
42
+L: sheepdog@lists.wpkg.org
43
+S: Odd Fixes
44
F: block/sheepdog.c
45
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
46
47
VHDX
48
-M: Jeff Cody <jcody@redhat.com>
49
+M: Jeff Cody <codyprime@gmail.com>
50
L: qemu-block@nongnu.org
51
S: Supported
52
F: block/vhdx*
53
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
54
55
VDI
56
M: Stefan Weil <sw@weilnetz.de>
57
@@ -XXX,XX +XXX,XX @@ F: docs/interop/nbd.txt
58
T: git https://repo.or.cz/qemu/ericb.git nbd
59
60
NFS
61
-M: Jeff Cody <jcody@redhat.com>
62
M: Peter Lieven <pl@kamp.de>
63
L: qemu-block@nongnu.org
64
S: Maintained
65
F: block/nfs.c
66
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
67
68
SSH
69
M: Richard W.M. Jones <rjones@redhat.com>
70
-M: Jeff Cody <jcody@redhat.com>
71
L: qemu-block@nongnu.org
72
S: Supported
73
F: block/ssh.c
74
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
75
76
CURL
77
-M: Jeff Cody <jcody@redhat.com>
78
L: qemu-block@nongnu.org
79
S: Supported
80
F: block/curl.c
81
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
82
83
GLUSTER
84
-M: Jeff Cody <jcody@redhat.com>
85
L: qemu-block@nongnu.org
86
S: Supported
87
F: block/gluster.c
88
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
89
90
Null Block Driver
91
M: Fam Zheng <fam@euphon.net>
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
1
3
At this moment, QEMU attempts to create/load/delete snapshots
4
by using either an ID (id_str) or a name. The problem is that the code
5
isn't consistent of whether the entered argument is an ID or a name,
6
causing unexpected behaviors.
7
8
For example, when creating snapshots via savevm <arg>, what happens is that
9
"arg" is treated as both name and id_str. In a guest without snapshots, create
10
a single snapshot via savevm:
11
12
(qemu) savevm 0
13
(qemu) info snapshots
14
List of snapshots present on all disks:
15
ID TAG VM SIZE DATE VM CLOCK
16
-- 0 741M 2018-07-31 13:39:56 00:41:25.313
17
18
A snapshot with name "0" is created. ID is hidden from the user, but the
19
ID is a non-zero integer that starts at "1". Thus, this snapshot has
20
id_str=1, TAG="0". Creating a second snapshot with arg = 1, the first one
21
is deleted:
22
23
(qemu) savevm 1
24
(qemu) info snapshots
25
List of snapshots present on all disks:
26
ID TAG VM SIZE DATE VM CLOCK
27
-- 1 741M 2018-07-31 13:42:14 00:41:55.252
28
29
What happened?
30
31
- when creating the second snapshot, a verification is done inside
32
bdrv_all_delete_snapshot to delete any existing snapshots that matches an
33
string argument. Here, the code calls bdrv_all_delete_snapshot("1", ...);
34
35
- bdrv_all_delete_snapshot calls bdrv_snapshot_find(..., "1") for each
36
BlockDriverState of the guest. And this is where things goes tilting:
37
bdrv_snapshot_find does a search by both id_str and name. It finds
38
out that there is a snapshot that has id_str = 1, stores a reference
39
to the snapshot in the sn_info pointer and then returns match found;
40
41
- since a match was found, a call to bdrv_snapshot_delete_by_id_or_name() is
42
made. This function ignores the pointer written by bdrv_snapshot_find. Instead,
43
it deletes the snapshot using bdrv_snapshot_delete() calling it first with
44
id_str = 1. If it fails to delete, then it calls it again with name = 1.
45
46
- after all that, QEMU creates the new snapshot, that has id_str = 1 and
47
name = 1. The user is left wondering that happened with the first snapshot
48
created. Similar bugs can be triggered when using loadvm and delvm.
49
50
Before contemplating discarding the use of ID input in these operations,
51
I've searched the code of what would be the implications. My findings
52
are:
53
54
- the RBD and Sheepdog drivers don't care. Both uses the 'name' field as
55
key in their logic, making id_str = name when appropriate.
56
replay-snapshot.c does not make any special use of id_str;
57
58
- qcow2 uses id_str as an unique identifier but it is automatically
59
calculated, not being influenced by user input. Other than that, there are
60
no distinguish operations made only with id_str;
61
62
- in blockdev.c, the delete operation uses a match of both id_str AND
63
name. Given that id_str is either a copy of 'name' or auto-generated,
64
we're fine here.
65
66
This gives motivation to not consider ID as a valid user input in HMP
67
commands - sticking with 'name' input only is more consistent. To
68
accomplish that, the following changes were made in this patch:
69
70
- bdrv_snapshot_find() does not match for id_str anymore, only 'name'. The
71
function is called in save_snapshot(), load_snapshot(), bdrv_all_delete_snapshot()
72
and bdrv_all_find_snapshot(). This change makes the search function more
73
predictable and does not change the behavior of any underlying code that uses
74
these affected functions, which are related to HMP (which is fine) and the
75
main loop inside vl.c (which doesn't care about it anyways);
76
77
- bdrv_all_delete_snapshot() does not call bdrv_snapshot_delete_by_id_or_name
78
anymore. Instead, it uses the pointer returned by bdrv_snapshot_find to
79
erase the snapshot with the exact match of id_str an name. This function
80
is called in save_snapshot and hmp_delvm, thus this change produces the
81
intended effect;
82
83
- documentation changes to reflect the new behavior. I consider this to
84
be an API fix instead of an API change - the user was already creating
85
snapshots using 'name', but now he/she will also enjoy a consistent
86
behavior.
87
88
Ideally we would get rid of the id_str field entirely, but this would have
89
repercussions on existing snapshots. Another day perhaps.
90
91
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
92
Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
93
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
94
---
95
block/snapshot.c | 5 +++--
96
hmp-commands.hx | 32 ++++++++++++++++++++------------
97
2 files changed, 23 insertions(+), 14 deletions(-)
98
99
diff --git a/block/snapshot.c b/block/snapshot.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/snapshot.c
102
+++ b/block/snapshot.c
103
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
104
}
105
for (i = 0; i < nb_sns; i++) {
106
sn = &sn_tab[i];
107
- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
108
+ if (!strcmp(sn->name, name)) {
109
*sn_info = *sn;
110
ret = 0;
111
break;
112
@@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
113
aio_context_acquire(ctx);
114
if (bdrv_can_snapshot(bs) &&
115
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
116
- ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
117
+ ret = bdrv_snapshot_delete(bs, snapshot->id_str,
118
+ snapshot->name, err);
119
}
120
aio_context_release(ctx);
121
if (ret < 0) {
122
diff --git a/hmp-commands.hx b/hmp-commands.hx
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hmp-commands.hx
125
+++ b/hmp-commands.hx
126
@@ -XXX,XX +XXX,XX @@ ETEXI
127
{
128
.name = "savevm",
129
.args_type = "name:s?",
130
- .params = "[tag|id]",
131
- .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
132
+ .params = "tag",
133
+ .help = "save a VM snapshot. If no tag is provided, a new snapshot is created",
134
.cmd = hmp_savevm,
135
},
136
137
STEXI
138
-@item savevm [@var{tag}|@var{id}]
139
+@item savevm @var{tag}
140
@findex savevm
141
Create a snapshot of the whole virtual machine. If @var{tag} is
142
provided, it is used as human readable identifier. If there is already
143
-a snapshot with the same tag or ID, it is replaced. More info at
144
+a snapshot with the same tag, it is replaced. More info at
145
@ref{vm_snapshots}.
146
+
147
+Since 4.0, savevm stopped allowing the snapshot id to be set, accepting
148
+only @var{tag} as parameter.
149
ETEXI
150
151
{
152
.name = "loadvm",
153
.args_type = "name:s",
154
- .params = "tag|id",
155
- .help = "restore a VM snapshot from its tag or id",
156
+ .params = "tag",
157
+ .help = "restore a VM snapshot from its tag",
158
.cmd = hmp_loadvm,
159
.command_completion = loadvm_completion,
160
},
161
162
STEXI
163
-@item loadvm @var{tag}|@var{id}
164
+@item loadvm @var{tag}
165
@findex loadvm
166
Set the whole virtual machine to the snapshot identified by the tag
167
-@var{tag} or the unique snapshot ID @var{id}.
168
+@var{tag}.
169
+
170
+Since 4.0, loadvm stopped accepting snapshot id as parameter.
171
ETEXI
172
173
{
174
.name = "delvm",
175
.args_type = "name:s",
176
- .params = "tag|id",
177
- .help = "delete a VM snapshot from its tag or id",
178
+ .params = "tag",
179
+ .help = "delete a VM snapshot from its tag",
180
.cmd = hmp_delvm,
181
.command_completion = delvm_completion,
182
},
183
184
STEXI
185
-@item delvm @var{tag}|@var{id}
186
+@item delvm @var{tag}
187
@findex delvm
188
-Delete the snapshot identified by @var{tag} or @var{id}.
189
+Delete the snapshot identified by @var{tag}.
190
+
191
+Since 4.0, delvm stopped deleting snapshots by snapshot id, accepting
192
+only @var{tag} as parameter.
193
ETEXI
194
195
{
196
--
197
2.20.1
198
199
diff view generated by jsdifflib
1
The only caller of nbd_read_eof() is nbd_receive_reply(), so it doesn't
1
This patch makes the raw image the same size as the file in a different
2
have to live in the header file, but can move next to its caller.
2
format that is mirrored as raw to it to avoid errors when mirror starts
3
3
to enforce that source and target are the same size.
4
Also add the missing coroutine_fn to the function and its caller.
4
5
We check only that the first 512 bytes are zeroed (instead of 64k)
6
because some image formats create image files that are smaller than 64k,
7
so trying to read 64k would result in I/O errors. Apart from this, 512
8
is more appropriate anyway because the raw format driver protects
9
specifically the first 512 bytes.
5
10
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>
12
Message-Id: <20200511135825.219437-2-kwolf@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
16
---
9
include/block/nbd.h | 3 ++-
17
tests/qemu-iotests/109 | 10 ++---
10
nbd/nbd-internal.h | 19 -------------------
18
tests/qemu-iotests/109.out | 74 +++++++++++++-------------------
11
nbd/client.c | 22 +++++++++++++++++++++-
19
tests/qemu-iotests/common.filter | 5 +++
12
3 files changed, 23 insertions(+), 21 deletions(-)
20
3 files changed, 41 insertions(+), 48 deletions(-)
13
21
14
diff --git a/include/block/nbd.h b/include/block/nbd.h
22
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/109
25
+++ b/tests/qemu-iotests/109
26
@@ -XXX,XX +XXX,XX @@ for fmt in qcow qcow2 qed vdi vmdk vpc; do
27
echo "=== Writing a $fmt header into raw ==="
28
echo
29
30
- _make_test_img 64M
31
TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M
32
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
33
34
# This first test should fail: The image format was probed, we may not
35
# write an image header at the start of the image
36
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
37
_filter_block_job_len
38
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
39
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
40
41
42
# When raw was explicitly specified, the same must succeed
43
@@ -XXX,XX +XXX,XX @@ for sample_img in empty.bochs iotest-dirtylog-10G-4M.vhdx parallels-v1 \
44
45
# Can't use _use_sample_img because that isn't designed to be used multiple
46
# times and it overwrites $TEST_IMG (both breaks cleanup)
47
- _make_test_img 64M
48
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
49
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
50
51
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
52
_filter_block_job_offset | _filter_block_job_len
53
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
54
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
55
56
run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY"
57
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
58
@@ -XXX,XX +XXX,XX @@ echo "=== Write legitimate MBR into raw ==="
59
echo
60
61
for sample_img in grub_mbr.raw; do
62
- _make_test_img 64M
63
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
64
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
65
66
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY"
67
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
68
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
15
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/nbd.h
70
--- a/tests/qemu-iotests/109.out
17
+++ b/include/block/nbd.h
71
+++ b/tests/qemu-iotests/109.out
18
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
72
@@ -XXX,XX +XXX,XX @@ QA output created by 109
19
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
73
20
Error **errp);
74
=== Writing a qcow header into raw ===
21
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
75
22
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
76
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
23
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
77
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
24
+ Error **errp);
78
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
25
int nbd_client(int fd);
79
{ 'execute': 'qmp_capabilities' }
26
int nbd_disconnect(int fd);
80
{"return": {}}
27
int nbd_errno_to_system_errno(int err);
81
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
28
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
82
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
83
{"execute":"quit"}
84
{"return": {}}
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
86
-read 65536/65536 bytes at offset 0
87
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
88
+read 512/512 bytes at offset 0
89
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
90
{ 'execute': 'qmp_capabilities' }
91
{"return": {}}
92
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
93
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
94
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
95
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
96
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
97
-Warning: Image size mismatch!
98
Images are identical.
99
100
=== Writing a qcow2 header into raw ===
101
102
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
103
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
104
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
105
{ 'execute': 'qmp_capabilities' }
106
{"return": {}}
107
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
108
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
109
{"execute":"quit"}
110
{"return": {}}
111
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
112
-read 65536/65536 bytes at offset 0
113
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
114
+read 512/512 bytes at offset 0
115
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
116
{ 'execute': 'qmp_capabilities' }
117
{"return": {}}
118
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
119
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
120
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
121
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
122
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
123
-Warning: Image size mismatch!
124
Images are identical.
125
126
=== Writing a qed header into raw ===
127
128
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
129
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
130
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
131
{ 'execute': 'qmp_capabilities' }
132
{"return": {}}
133
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
134
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
135
{"execute":"quit"}
136
{"return": {}}
137
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
138
-read 65536/65536 bytes at offset 0
139
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
140
+read 512/512 bytes at offset 0
141
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
142
{ 'execute': 'qmp_capabilities' }
143
{"return": {}}
144
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
145
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
146
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
147
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
148
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
149
-Warning: Image size mismatch!
150
Images are identical.
151
152
=== Writing a vdi header into raw ===
153
154
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
155
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
156
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
157
{ 'execute': 'qmp_capabilities' }
158
{"return": {}}
159
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
160
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
161
{"execute":"quit"}
162
{"return": {}}
163
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
164
-read 65536/65536 bytes at offset 0
165
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
166
+read 512/512 bytes at offset 0
167
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
{ 'execute': 'qmp_capabilities' }
169
{"return": {}}
170
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
171
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
172
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
173
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
174
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
175
-Warning: Image size mismatch!
176
Images are identical.
177
178
=== Writing a vmdk header into raw ===
179
180
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
181
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
182
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
183
{ 'execute': 'qmp_capabilities' }
184
{"return": {}}
185
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
186
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
187
{"execute":"quit"}
188
{"return": {}}
189
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
190
-read 65536/65536 bytes at offset 0
191
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
192
+read 512/512 bytes at offset 0
193
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
{ 'execute': 'qmp_capabilities' }
195
{"return": {}}
196
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
197
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
198
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
199
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
200
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
201
-Warning: Image size mismatch!
202
Images are identical.
203
204
=== Writing a vpc header into raw ===
205
206
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
207
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
208
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
209
{ 'execute': 'qmp_capabilities' }
210
{"return": {}}
211
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
212
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
213
{"execute":"quit"}
214
{"return": {}}
215
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
216
-read 65536/65536 bytes at offset 0
217
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
218
+read 512/512 bytes at offset 0
219
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
220
{ 'execute': 'qmp_capabilities' }
221
{"return": {}}
222
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
223
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
224
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
225
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
226
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
227
-Warning: Image size mismatch!
228
Images are identical.
229
230
=== Copying sample image empty.bochs into raw ===
231
232
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
233
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
234
{ 'execute': 'qmp_capabilities' }
235
{"return": {}}
236
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
237
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
238
{"execute":"quit"}
239
{"return": {}}
240
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
241
-read 65536/65536 bytes at offset 0
242
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
243
+read 512/512 bytes at offset 0
244
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
245
{ 'execute': 'qmp_capabilities' }
246
{"return": {}}
247
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
248
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
249
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
250
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
251
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
252
-Warning: Image size mismatch!
253
Images are identical.
254
255
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
256
257
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
258
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
259
{ 'execute': 'qmp_capabilities' }
260
{"return": {}}
261
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
262
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
263
{"execute":"quit"}
264
{"return": {}}
265
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
266
-read 65536/65536 bytes at offset 0
267
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
268
+read 512/512 bytes at offset 0
269
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
{ 'execute': 'qmp_capabilities' }
271
{"return": {}}
272
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
273
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
274
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
275
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
276
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
277
-Warning: Image size mismatch!
278
Images are identical.
279
280
=== Copying sample image parallels-v1 into raw ===
281
282
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
283
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
284
{ 'execute': 'qmp_capabilities' }
285
{"return": {}}
286
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
287
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
288
{"execute":"quit"}
289
{"return": {}}
290
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
291
-read 65536/65536 bytes at offset 0
292
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
293
+read 512/512 bytes at offset 0
294
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
{ 'execute': 'qmp_capabilities' }
296
{"return": {}}
297
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
298
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
299
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
300
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
301
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
302
-Warning: Image size mismatch!
303
Images are identical.
304
305
=== Copying sample image simple-pattern.cloop into raw ===
306
307
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
308
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
309
{ 'execute': 'qmp_capabilities' }
310
{"return": {}}
311
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
312
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
313
{"execute":"quit"}
314
{"return": {}}
315
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
316
-read 65536/65536 bytes at offset 0
317
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
318
+read 512/512 bytes at offset 0
319
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
320
{ 'execute': 'qmp_capabilities' }
321
{"return": {}}
322
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
323
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 0
324
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
325
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
326
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
327
-Warning: Image size mismatch!
328
Images are identical.
329
330
=== Write legitimate MBR into raw ===
331
332
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
333
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
334
{ 'execute': 'qmp_capabilities' }
335
{"return": {}}
336
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
337
@@ -XXX,XX +XXX,XX @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
338
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
339
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
340
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
341
-Warning: Image size mismatch!
342
Images are identical.
343
{ 'execute': 'qmp_capabilities' }
344
{"return": {}}
345
@@ -XXX,XX +XXX,XX @@ Images are identical.
346
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
347
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
348
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
349
-Warning: Image size mismatch!
350
Images are identical.
351
*** done
352
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
29
index XXXXXXX..XXXXXXX 100644
353
index XXXXXXX..XXXXXXX 100644
30
--- a/nbd/nbd-internal.h
354
--- a/tests/qemu-iotests/common.filter
31
+++ b/nbd/nbd-internal.h
355
+++ b/tests/qemu-iotests/common.filter
32
@@ -XXX,XX +XXX,XX @@
356
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
33
#define NBD_SET_TIMEOUT _IO(0xab, 9)
357
-e "s# compression_type=[a-zA-Z0-9]\\+##g"
34
#define NBD_SET_FLAGS _IO(0xab, 10)
35
36
-/* nbd_read_eof
37
- * Tries to read @size bytes from @ioc.
38
- * Returns 1 on success
39
- * 0 on eof, when no data was read (errp is not set)
40
- * negative errno on failure (errp is set)
41
- */
42
-static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
43
- Error **errp)
44
-{
45
- int ret;
46
-
47
- assert(size);
48
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
49
- if (ret < 0) {
50
- ret = -EIO;
51
- }
52
- return ret;
53
-}
54
-
55
/* nbd_write
56
* Writes @size bytes to @ioc. Returns 0 on success.
57
*/
58
diff --git a/nbd/client.c b/nbd/client.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/nbd/client.c
61
+++ b/nbd/client.c
62
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
63
return 0;
64
}
358
}
65
359
66
+/* nbd_read_eof
360
+_filter_img_create_size()
67
+ * Tries to read @size bytes from @ioc.
68
+ * Returns 1 on success
69
+ * 0 on eof, when no data was read (errp is not set)
70
+ * negative errno on failure (errp is set)
71
+ */
72
+static inline int coroutine_fn
73
+nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
74
+{
361
+{
75
+ int ret;
362
+ $SED -e "s# size=[0-9]\\+# size=SIZE#g"
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
+}
363
+}
84
+
364
+
85
/* nbd_receive_reply
365
_filter_img_info()
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
{
366
{
94
int ret;
367
if [[ "$1" == "--format-specific" ]]; then
95
const char *type;
96
--
368
--
97
2.20.1
369
2.25.4
98
370
99
371
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
229 relies on the mirror running into an I/O error when the target is
2
smaller than the source. After changing mirror to catch this condition
3
while starting the job, this test case won't get a job that is paused
4
for an I/O error any more. Use blkdebug instead to inject an error.
2
5
3
Test 110 tests relative backing filenames for complex BDS trees. Now
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
that the originally supposedly failing test passes, let us add a new
7
Reviewed-by: Eric Blake <eblake@redhat.com>
5
failing test: Quorum can never work automatically (without detecting
8
Message-Id: <20200511135825.219437-3-kwolf@redhat.com>
6
whether all child nodes have the same base directory, but that would be
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
rather inconsistent behavior).
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
tests/qemu-iotests/229 | 15 +++++++++++----
14
tests/qemu-iotests/229.out | 6 +++---
15
2 files changed, 14 insertions(+), 7 deletions(-)
8
16
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
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
18
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/110
19
--- a/tests/qemu-iotests/229
21
+++ b/tests/qemu-iotests/110
20
+++ b/tests/qemu-iotests/229
22
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
21
@@ -XXX,XX +XXX,XX @@ _cleanup()
23
_cleanup()
22
_cleanup_test_img
24
{
23
_rm_test_img "$TEST_IMG"
25
    _cleanup_test_img
24
_rm_test_img "$DEST_IMG"
26
+ rm -f "$TEST_IMG.copy"
25
+ rm -f "$TEST_DIR/blkdebug.conf"
27
}
26
}
28
trap "_cleanup; exit \$status" 0 1 2 3 15
27
trap "_cleanup; exit \$status" 0 1 2 3 15
29
28
29
@@ -XXX,XX +XXX,XX @@ _supported_os Linux
30
31
DEST_IMG="$TEST_DIR/d.$IMGFMT"
32
TEST_IMG="$TEST_DIR/b.$IMGFMT"
33
+BLKDEBUG_CONF="$TEST_DIR/blkdebug.conf"
34
35
_make_test_img 2M
36
-
37
-# destination for mirror will be too small, causing error
38
-TEST_IMG=$DEST_IMG _make_test_img 1M
39
+TEST_IMG=$DEST_IMG _make_test_img 2M
40
41
$QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io
42
30
@@ -XXX,XX +XXX,XX @@ echo
43
@@ -XXX,XX +XXX,XX @@ echo
31
# omit the image size; it should work anyway
44
echo '=== Starting drive-mirror, causing error & stop ==='
32
_make_test_img -b "$TEST_IMG_REL.base"
45
echo
33
46
34
+echo
47
+cat > "$BLKDEBUG_CONF" <<EOF
35
+echo '=== Nodes without a common directory ==='
48
+[inject-error]
36
+echo
49
+event = "write_aio"
50
+errno = "5"
51
+once = "on"
52
+EOF
37
+
53
+
38
+cp "$TEST_IMG" "$TEST_IMG.copy"
54
_send_qemu_cmd $QEMU_HANDLE \
39
+
55
"{'execute': 'drive-mirror',
40
+# Should inform us that the actual path of the backing file cannot be determined
56
'arguments': {'device': 'testdisk',
41
+TEST_IMG="json:{
57
'format': '$IMGFMT',
42
+ 'driver': '$IMGFMT',
58
- 'target': '$DEST_IMG',
43
+ 'file': {
59
+ 'target': 'blkdebug:$BLKDEBUG_CONF:$DEST_IMG',
44
+ 'driver': 'quorum',
60
'sync': 'full',
45
+ 'vote-threshold': 1,
61
'mode': 'existing',
46
+ 'children': [
62
'on-source-error': 'stop',
47
+ {
63
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
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
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/110.out
65
--- a/tests/qemu-iotests/229.out
65
+++ b/tests/qemu-iotests/110.out
66
+++ b/tests/qemu-iotests/229.out
66
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
67
@@ -XXX,XX +XXX,XX @@
67
=== Backing name is always relative to the backed image ===
68
QA output created by 229
68
69
Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=2097152
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
70
-Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=1048576
70
+
71
+Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=2097152
71
+=== Nodes without a common directory ===
72
wrote 2097152/2097152 bytes at offset 0
72
+
73
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
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
{'execute': 'qmp_capabilities'}
74
+file format: IMGFMT
75
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
75
+virtual size: 64M (67108864 bytes)
76
76
+backing file: t.IMGFMT.base (cannot determine actual path)
77
=== Starting drive-mirror, causing error & stop ===
78
79
-{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
80
+{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
81
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
82
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
83
{"return": {}}
84
@@ -XXX,XX +XXX,XX @@ wrote 2097152/2097152 bytes at offset 0
85
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
86
{"return": {}}
87
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
88
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
89
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 2097152, "speed": 0, "type": "mirror"}}
77
*** done
90
*** done
78
--
91
--
79
2.20.1
92
2.25.4
80
93
81
94
diff view generated by jsdifflib
1
When a drained node changes its AioContext, we need to move its
1
If the target is shorter than the source, mirror would copy data until
2
aio_disable_external() to the new context, too.
2
it reaches the end of the target and then fail with an I/O error when
3
trying to write past the end.
3
4
4
Without this fix, drain_end will try to reenable the new context, which
5
If the target is longer than the source, the mirror job would complete
5
has never been disabled, so an assertion failure is triggered.
6
successfully, but the target wouldn't actually be an accurate copy of
7
the source image (it would contain some additional garbage at the end).
8
9
Fix this by checking that both images have the same size when the job
10
starts.
6
11
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Message-Id: <20200511135825.219437-4-kwolf@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
18
---
10
block.c | 7 +++++++
19
block/mirror.c | 21 ++++++++++++---------
11
1 file changed, 7 insertions(+)
20
1 file changed, 12 insertions(+), 9 deletions(-)
12
21
13
diff --git a/block.c b/block.c
22
diff --git a/block/mirror.c b/block/mirror.c
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
24
--- a/block/mirror.c
16
+++ b/block.c
25
+++ b/block/mirror.c
17
@@ -XXX,XX +XXX,XX @@ void bdrv_detach_aio_context(BlockDriverState *bs)
26
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
18
bdrv_detach_aio_context(child->bs);
27
BlockDriverState *target_bs = blk_bs(s->target);
28
bool need_drain = true;
29
int64_t length;
30
+ int64_t target_length;
31
BlockDriverInfo bdi;
32
char backing_filename[2]; /* we only need 2 characters because we are only
33
checking for a NULL string */
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
35
goto immediate_exit;
19
}
36
}
20
37
21
+ if (bs->quiesce_counter) {
38
+ target_length = blk_getlength(s->target);
22
+ aio_enable_external(bs->aio_context);
39
+ if (target_length < 0) {
23
+ }
40
+ ret = target_length;
24
bs->aio_context = NULL;
41
+ goto immediate_exit;
25
}
26
27
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
28
return;
29
}
30
31
+ if (bs->quiesce_counter) {
32
+ aio_disable_external(new_context);
33
+ }
42
+ }
34
+
43
+
35
bs->aio_context = new_context;
44
/* Active commit must resize the base image if its size differs from the
36
45
* active layer. */
37
QLIST_FOREACH(child, &bs->children, next) {
46
if (s->base == blk_bs(s->target)) {
47
- int64_t base_length;
48
-
49
- base_length = blk_getlength(s->target);
50
- if (base_length < 0) {
51
- ret = base_length;
52
- goto immediate_exit;
53
- }
54
-
55
- if (s->bdev_length > base_length) {
56
+ if (s->bdev_length > target_length) {
57
ret = blk_truncate(s->target, s->bdev_length, false,
58
PREALLOC_MODE_OFF, 0, NULL);
59
if (ret < 0) {
60
goto immediate_exit;
61
}
62
}
63
+ } else if (s->bdev_length != target_length) {
64
+ error_setg(errp, "Source and target image have different sizes");
65
+ ret = -EINVAL;
66
+ goto immediate_exit;
67
}
68
69
if (s->bdev_length == 0) {
38
--
70
--
39
2.20.1
71
2.25.4
40
72
41
73
diff view generated by jsdifflib
1
nbd_client_attach_aio_context() schedules connection_co in the new
1
This tests that the mirror job catches situations where the target node
2
AioContext and this way reenters it in any arbitrary place that has
2
has a different size than the source node. It must also forbid resize
3
yielded. We can restrict this a bit to the function call where the
3
operations when the job is already running.
4
coroutine actually sits waiting when it's idle.
5
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
4
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-Id: <20200511135825.219437-5-kwolf@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
11
---
15
block/nbd-client.h | 1 +
12
tests/qemu-iotests/041 | 45 ++++++++++++++++++++++++++++++++++++++
16
block/nbd-client.c | 22 ++++++++++++++++++++++
13
tests/qemu-iotests/041.out | 4 ++--
17
2 files changed, 23 insertions(+)
14
2 files changed, 47 insertions(+), 2 deletions(-)
18
15
19
diff --git a/block/nbd-client.h b/block/nbd-client.h
16
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/041
19
+++ b/tests/qemu-iotests/041
20
@@ -XXX,XX +XXX,XX @@ class TestSingleBlockdev(TestSingleDrive):
21
target=self.qmp_target)
22
self.assert_qmp(result, 'error/class', 'GenericError')
23
24
+ def do_test_resize(self, device, node):
25
+ def pre_finalize():
26
+ if device:
27
+ result = self.vm.qmp('block_resize', device=device, size=65536)
28
+ self.assert_qmp(result, 'error/class', 'GenericError')
29
+
30
+ result = self.vm.qmp('block_resize', node_name=node, size=65536)
31
+ self.assert_qmp(result, 'error/class', 'GenericError')
32
+
33
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0', device='drive0',
34
+ sync='full', target=self.qmp_target,
35
+ auto_finalize=False, auto_dismiss=False)
36
+ self.assert_qmp(result, 'return', {})
37
+
38
+ result = self.vm.run_job('job0', auto_finalize=False,
39
+ pre_finalize=pre_finalize)
40
+ self.assertEqual(result, None)
41
+
42
+ def test_source_resize(self):
43
+ self.do_test_resize('drive0', 'top')
44
+
45
+ def test_target_resize(self):
46
+ self.do_test_resize(None, self.qmp_target)
47
+
48
+ def do_test_target_size(self, size):
49
+ result = self.vm.qmp('block_resize', node_name=self.qmp_target,
50
+ size=size)
51
+ self.assert_qmp(result, 'return', {})
52
+
53
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0',
54
+ device='drive0', sync='full', auto_dismiss=False,
55
+ target=self.qmp_target)
56
+ self.assert_qmp(result, 'return', {})
57
+
58
+ result = self.vm.run_job('job0')
59
+ self.assertEqual(result, 'Source and target image have different sizes')
60
+
61
+ def test_small_target(self):
62
+ self.do_test_target_size(self.image_len // 2)
63
+
64
+ def test_large_target(self):
65
+ self.do_test_target_size(self.image_len * 2)
66
+
67
test_large_cluster = None
68
test_image_not_found = None
69
test_small_buffer2 = None
70
@@ -XXX,XX +XXX,XX @@ class TestSingleDriveZeroLength(TestSingleDrive):
71
72
class TestSingleBlockdevZeroLength(TestSingleBlockdev):
73
image_len = 0
74
+ test_small_target = None
75
+ test_large_target = None
76
77
class TestSingleDriveUnalignedLength(TestSingleDrive):
78
image_len = 1025 * 1024
79
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
20
index XXXXXXX..XXXXXXX 100644
80
index XXXXXXX..XXXXXXX 100644
21
--- a/block/nbd-client.h
81
--- a/tests/qemu-iotests/041.out
22
+++ b/block/nbd-client.h
82
+++ b/tests/qemu-iotests/041.out
23
@@ -XXX,XX +XXX,XX @@ typedef struct NBDClientSession {
83
@@ -XXX,XX +XXX,XX @@
24
84
-..............................................................................................
25
NBDClientRequest requests[MAX_NBD_REQUESTS];
85
+........................................................................................................
26
NBDReply reply;
86
----------------------------------------------------------------------
27
+ BlockDriverState *bs;
87
-Ran 94 tests
28
bool quit;
88
+Ran 104 tests
29
} NBDClientSession;
89
30
90
OK
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
--
91
--
95
2.20.1
92
2.25.4
96
93
97
94
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Lukas Straub <lukasstraub2@web.de>
2
2
3
L1 table entries have a field to store the offset of an L2 table.
3
If qemu in colo secondary mode is stopped, it crashes because
4
The rest of the bits of the entry are currently reserved except from
4
s->backup_job is canceled twice: First with job_cancel_sync_all()
5
bit 63, which stores the COPIED flag.
5
in qemu_cleanup() and then in replication_stop().
6
6
7
The offset is always taken from the entry using L1E_OFFSET_MASK to
7
Fix this by assigning NULL to s->backup_job when the job completes
8
ensure that we only use the bits that belong to that field.
8
so replication_stop() and replication_do_checkpoint() won't touch
9
the job.
9
10
10
While that mask is used every time we read from the L1 table, it is
11
Signed-off-by: Lukas Straub <lukasstraub2@web.de>
11
never used when we write to it. Due to the limits set elsewhere in the
12
Message-Id: <20200511090801.7ed5d8f3@luklap>
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>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
14
---
20
block/qcow2-cluster.c | 3 +++
15
block/replication.c | 2 ++
21
1 file changed, 3 insertions(+)
16
1 file changed, 2 insertions(+)
22
17
23
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
18
diff --git a/block/replication.c b/block/replication.c
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2-cluster.c
20
--- a/block/replication.c
26
+++ b/block/qcow2-cluster.c
21
+++ b/block/replication.c
27
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
22
@@ -XXX,XX +XXX,XX @@ static void backup_job_cleanup(BlockDriverState *bs)
28
goto fail;
23
BDRVReplicationState *s = bs->opaque;
29
}
24
BlockDriverState *top_bs;
30
25
31
+ /* The offset must fit in the offset field of the L1 table entry */
26
+ s->backup_job = NULL;
32
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
33
+
27
+
34
/* If we're allocating the table at offset 0 then something is wrong */
28
top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
35
if (l2_offset == 0) {
29
if (!top_bs) {
36
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
30
return;
37
--
31
--
38
2.20.1
32
2.25.4
39
33
40
34
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We need to fix only a few places so that iotests.py can pass
2
mypy --disallow-incomplete-defs, which seems to be a desirable option to
3
have enabled in the long run.
2
4
3
This function queries a node; since we cannot do that right now, it
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
executes query-named-block-nodes and returns the matching node's object.
6
Message-Id: <20200511163529.349329-2-kwolf@redhat.com>
5
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.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
---
10
---
13
tests/qemu-iotests/iotests.py | 7 +++++++
11
tests/qemu-iotests/iotests.py | 8 ++++----
14
1 file changed, 7 insertions(+)
12
1 file changed, 4 insertions(+), 4 deletions(-)
15
13
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
16
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
17
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
18
@@ -XXX,XX +XXX,XX @@ def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
21
else:
19
if supported_cache_modes and (cachemode not in supported_cache_modes):
22
iotests.log(ev)
20
notrun('not suitable for this cache mode: %s' % cachemode)
23
21
24
+ def node_info(self, node_name):
22
-def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
25
+ nodes = self.qmp('query-named-block-nodes')
23
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
26
+ for x in nodes['return']:
24
if supported_aio_modes and (aiomode not in supported_aio_modes):
27
+ if x['node-name'] == node_name:
25
notrun('not suitable for this aio mode: %s' % aiomode)
28
+ return x
26
29
+ return None
27
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=(), read_only=False):
30
+
28
'''Skip Test Decorator
31
29
Runs the test if all the required formats are whitelisted'''
32
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
30
def skip_test_decorator(func):
31
- def func_wrapper(test_case: QMPTestCase, *args, **kwargs):
32
+ def func_wrapper(test_case: QMPTestCase, *args: List[Any],
33
+ **kwargs: Dict[str, Any]) -> None:
34
if callable(required_formats):
35
fmts = required_formats(test_case)
36
else:
37
@@ -XXX,XX +XXX,XX @@ def skip_if_unsupported(required_formats=(), read_only=False):
38
if usf_list:
39
msg = f'{test_case}: formats {usf_list} are not whitelisted'
40
test_case.case_skip(msg)
41
- return None
42
else:
43
- return func(test_case, *args, **kwargs)
44
+ func(test_case, *args, **kwargs)
45
return func_wrapper
46
return skip_test_decorator
33
47
34
--
48
--
35
2.20.1
49
2.25.4
36
50
37
51
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We made sure that iotests.py passes pylint. It would be a shame if we
2
allowed new patches in that break this again, so let's just add a
3
meta-test case that runs pylint on it.
2
4
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
While we don't pass mypy --strict yet, we can already run it with a few
4
Message-id: 20190201192935.18394-32-mreitz@redhat.com
6
options that would be part of --strict to make sure that we won't
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
regress on these aspects at least until we can enable the full thing.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20200511163529.349329-3-kwolf@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
14
---
7
tests/qemu-iotests/224 | 139 +++++++++++++++++++++++++++++++++++++
15
tests/qemu-iotests/297 | 44 ++++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/224.out | 18 +++++
16
tests/qemu-iotests/297.out | 3 +++
9
tests/qemu-iotests/group | 1 +
17
tests/qemu-iotests/group | 1 +
10
3 files changed, 158 insertions(+)
18
3 files changed, 48 insertions(+)
11
create mode 100755 tests/qemu-iotests/224
19
create mode 100755 tests/qemu-iotests/297
12
create mode 100644 tests/qemu-iotests/224.out
20
create mode 100644 tests/qemu-iotests/297.out
13
21
14
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
22
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
15
new file mode 100755
23
new file mode 100755
16
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
17
--- /dev/null
25
--- /dev/null
18
+++ b/tests/qemu-iotests/224
26
+++ b/tests/qemu-iotests/297
19
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python
28
+#!/usr/bin/env bash
21
+#
29
+#
22
+# Test json:{} filenames with qemu-internal BDSs
30
+# Copyright (C) 2020 Red Hat, Inc.
23
+# (the one of commit, to be precise)
24
+#
25
+# Copyright (C) 2018 Red Hat, Inc.
26
+#
31
+#
27
+# This program is free software; you can redistribute it and/or modify
32
+# 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
33
+# 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
34
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
35
+# (at your option) any later version.
...
...
34
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+# GNU General Public License for more details.
40
+# GNU General Public License for more details.
36
+#
41
+#
37
+# You should have received a copy of the GNU General Public License
42
+# 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/>.
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
40
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
41
+
44
+
42
+import iotests
45
+seq=$(basename $0)
43
+from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
46
+echo "QA output created by $seq"
44
+ filter_qmp_imgfmt
45
+import json
46
+
47
+
47
+# Need backing file support (for arbitrary backing formats)
48
+status=1    # failure is the default!
48
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
49
+iotests.verify_platform(['linux'])
50
+
49
+
50
+# get standard environment
51
+. ./common.rc
51
+
52
+
52
+# There are two variations of this test:
53
+if ! type -p "pylint-3" > /dev/null; then
53
+# (1) We do not set filter_node_name. In that case, the commit_top
54
+ _notrun "pylint-3 not found"
54
+# driver should not appear anywhere.
55
+fi
55
+# (2) We do set filter_node_name. In that case, it should appear.
56
+if ! type -p "mypy" > /dev/null; then
56
+#
57
+ _notrun "mypy not found"
57
+# This for loop executes both.
58
+fi
58
+for filter_node_name in False, True:
59
+ log('')
60
+ log('--- filter_node_name: %s ---' % filter_node_name)
61
+ log('')
62
+
59
+
63
+ with iotests.FilePath('base.img') as base_img_path, \
60
+pylint-3 --score=n iotests.py
64
+ iotests.FilePath('mid.img') as mid_img_path, \
65
+ iotests.FilePath('top.img') as top_img_path, \
66
+ iotests.VM() as vm:
67
+
61
+
68
+ assert qemu_img('create', '-f', iotests.imgfmt,
62
+MYPYPATH=../../python/ mypy --warn-unused-configs --disallow-subclassing-any \
69
+ base_img_path, '64M') == 0
63
+ --disallow-any-generics --disallow-incomplete-defs \
70
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
64
+ --disallow-untyped-decorators --no-implicit-optional \
71
+ mid_img_path) == 0
65
+ --warn-redundant-casts --warn-unused-ignores \
72
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
66
+ --no-implicit-reexport iotests.py
73
+ top_img_path) == 0
74
+
67
+
75
+ # Something to commit
68
+# success, all done
76
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
69
+echo "*** done"
77
+
70
+rm -f $seq.full
78
+ vm.launch()
71
+status=0
79
+
72
diff --git a/tests/qemu-iotests/297.out b/tests/qemu-iotests/297.out
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
73
new file mode 100644
161
index XXXXXXX..XXXXXXX
74
index XXXXXXX..XXXXXXX
162
--- /dev/null
75
--- /dev/null
163
+++ b/tests/qemu-iotests/224.out
76
+++ b/tests/qemu-iotests/297.out
164
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@
165
+
78
+QA output created by 297
166
+--- filter_node_name: False ---
79
+Success: no issues found in 1 source file
167
+
80
+*** done
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
81
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
184
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qemu-iotests/group
83
--- a/tests/qemu-iotests/group
186
+++ b/tests/qemu-iotests/group
84
+++ b/tests/qemu-iotests/group
187
@@ -XXX,XX +XXX,XX @@
85
@@ -XXX,XX +XXX,XX @@
188
221 rw auto quick
86
289 rw quick
189
222 rw auto quick
87
290 rw auto quick
190
223 rw auto quick
88
292 rw auto quick
191
+224 rw auto quick
89
+297 meta
192
225 rw auto quick
193
226 auto quick
194
227 auto quick
195
--
90
--
196
2.20.1
91
2.25.4
197
92
198
93
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Make bdrv_get_full_backing_filename() return an allocated string instead
3
Right now, all users of bdrv_make_empty() call the BlockDriver method
4
of placing the result in a caller-provided buffer.
4
directly. That is not only bad style, it is also wrong, unless the
5
caller has a BdrvChild with a WRITE or WRITE_UNCHANGED permission.
6
(WRITE_UNCHANGED suffices, because callers generally use this function
7
to clear a node with a backing file after a commit operation.)
8
9
Introduce bdrv_make_empty() that verifies that it does.
5
10
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-Id: <20200429141126.85159-2-mreitz@redhat.com>
8
Message-id: 20190201192935.18394-12-mreitz@redhat.com
13
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
include/block/block.h | 3 +--
16
include/block/block.h | 1 +
12
block.c | 48 +++++++++++++++----------------------------
17
block.c | 23 +++++++++++++++++++++++
13
block/qapi.c | 12 ++---------
18
2 files changed, 24 insertions(+)
14
3 files changed, 20 insertions(+), 43 deletions(-)
15
19
16
diff --git a/include/block/block.h b/include/block/block.h
20
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
22
--- a/include/block/block.h
19
+++ b/include/block/block.h
23
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
24
@@ -XXX,XX +XXX,XX @@ BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
21
25
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
22
void bdrv_get_backing_filename(BlockDriverState *bs,
26
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
23
char *filename, int filename_size);
27
int bdrv_commit(BlockDriverState *bs);
24
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
28
+int bdrv_make_empty(BdrvChild *c, Error **errp);
25
- char *dest, size_t sz, Error **errp);
29
int bdrv_change_backing_file(BlockDriverState *bs,
26
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
30
const char *backing_file, const char *backing_fmt);
27
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
31
void bdrv_register(BlockDriver *bdrv);
28
const char *backing,
29
Error **errp);
30
diff --git a/block.c b/block.c
32
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
34
--- a/block.c
33
+++ b/block.c
35
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
36
@@ -XXX,XX +XXX,XX @@ void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
35
}
37
38
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
36
}
39
}
37
38
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
39
- Error **errp)
40
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
41
{
42
char *backed;
43
- char *full_name;
44
- Error *local_error = NULL;
45
46
bdrv_refresh_filename(bs);
47
48
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
49
-
50
- full_name = bdrv_get_full_backing_filename_from_filename(backed,
51
- bs->backing_file,
52
- &local_error);
53
- if (full_name) {
54
- pstrcpy(dest, sz, full_name);
55
- g_free(full_name);
56
- } else if (local_error) {
57
- error_propagate(errp, local_error);
58
- } else if (sz > 0) {
59
- *dest = '\0';
60
- }
61
+ return bdrv_get_full_backing_filename_from_filename(backed,
62
+ bs->backing_file,
63
+ errp);
64
}
65
66
void bdrv_register(BlockDriver *bdrv)
67
@@ -XXX,XX +XXX,XX @@ out:
68
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
69
const char *bdref_key, Error **errp)
70
{
71
- char *backing_filename = g_malloc0(PATH_MAX);
72
+ char *backing_filename = NULL;
73
char *bdref_key_dot;
74
const char *reference = NULL;
75
int ret = 0;
76
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
77
*/
78
reference = qdict_get_try_str(parent_options, bdref_key);
79
if (reference || qdict_haskey(options, "file.filename")) {
80
- backing_filename[0] = '\0';
81
+ /* keep backing_filename NULL */
82
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
83
qobject_unref(options);
84
goto free_exit;
85
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
86
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
87
}
88
89
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
90
- &local_err);
91
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
92
if (local_err) {
93
ret = -EINVAL;
94
error_propagate(errp, local_err);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
96
qdict_put_str(options, "driver", bs->backing_format);
97
}
98
99
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
100
- reference, options, 0, bs, &child_backing,
101
- errp);
102
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
103
+ &child_backing, errp);
104
if (!backing_hd) {
105
bs->open_flags |= BDRV_O_NO_BACKING;
106
error_prepend(errp, "Could not open backing file: ");
107
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
108
int is_protocol = 0;
109
BlockDriverState *curr_bs = NULL;
110
BlockDriverState *retval = NULL;
111
- Error *local_error = NULL;
112
113
if (!bs || !bs->drv || !backing_file) {
114
return NULL;
115
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
116
/* If either of the filename paths is actually a protocol, then
117
* compare unmodified paths; otherwise make paths relative */
118
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
119
+ char *backing_file_full_ret;
120
+
40
+
121
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
41
+int bdrv_make_empty(BdrvChild *c, Error **errp)
122
retval = curr_bs->backing->bs;
42
+{
123
break;
43
+ BlockDriver *drv = c->bs->drv;
124
}
44
+ int ret;
125
/* Also check against the full backing filename for the image */
45
+
126
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
46
+ assert(c->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED));
127
- &local_error);
47
+
128
- if (local_error == NULL) {
48
+ if (!drv->bdrv_make_empty) {
129
- if (strcmp(backing_file, backing_file_full) == 0) {
49
+ error_setg(errp, "%s does not support emptying nodes",
130
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
50
+ drv->format_name);
131
+ NULL);
51
+ return -ENOTSUP;
132
+ if (backing_file_full_ret) {
52
+ }
133
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
53
+
134
+ g_free(backing_file_full_ret);
54
+ ret = drv->bdrv_make_empty(c->bs);
135
+ if (equal) {
55
+ if (ret < 0) {
136
retval = curr_bs->backing->bs;
56
+ error_setg_errno(errp, -ret, "Failed to empty %s",
137
break;
57
+ c->bs->filename);
138
}
58
+ return ret;
139
- } else {
59
+ }
140
- error_free(local_error);
60
+
141
- local_error = NULL;
61
+ return 0;
142
}
62
+}
143
} else {
144
/* If not an absolute filename path, make it relative to the current
145
diff --git a/block/qapi.c b/block/qapi.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/block/qapi.c
148
+++ b/block/qapi.c
149
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
150
151
backing_filename = bs->backing_file;
152
if (backing_filename[0] != '\0') {
153
- char *backing_filename2 = g_malloc0(PATH_MAX);
154
+ char *backing_filename2;
155
info->backing_filename = g_strdup(backing_filename);
156
info->has_backing_filename = true;
157
- bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
158
- if (err) {
159
- /* Can't reconstruct the full backing filename, so we must omit
160
- * this field and apply a Best Effort to this query. */
161
- g_free(backing_filename2);
162
- backing_filename2 = NULL;
163
- error_free(err);
164
- err = NULL;
165
- }
166
+ backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
167
168
/* Always report the full_backing_filename if present, even if it's the
169
* same as backing_filename. That they are same is useful info. */
170
--
63
--
171
2.20.1
64
2.25.4
172
65
173
66
diff view generated by jsdifflib
1
For some users of BlockBackends, just increasing the in_flight counter
1
From: Max Reitz <mreitz@redhat.com>
2
is easier than implementing separate handlers in BlockDevOps. Make the
3
helper functions for this public.
4
2
3
Two callers of BlockDriver.bdrv_make_empty() remain that should not call
4
this method directly. Both do not have access to a BdrvChild, but they
5
can use a BlockBackend, so we add this function that lets them use it.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200429141126.85159-4-mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
11
---
7
include/sysemu/block-backend.h | 2 ++
12
include/sysemu/block-backend.h | 2 ++
8
block/block-backend.c | 4 ++--
13
block/block-backend.c | 10 ++++++++++
9
2 files changed, 4 insertions(+), 2 deletions(-)
14
2 files changed, 12 insertions(+)
10
15
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
16
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/include/sysemu/block-backend.h
18
--- a/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
19
+++ b/include/sysemu/block-backend.h
15
@@ -XXX,XX +XXX,XX @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
20
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
16
int blk_co_flush(BlockBackend *blk);
21
17
int blk_flush(BlockBackend *blk);
22
const BdrvChild *blk_root(BlockBackend *blk);
18
int blk_commit_all(void);
23
19
+void blk_inc_in_flight(BlockBackend *blk);
24
+int blk_make_empty(BlockBackend *blk, Error **errp);
20
+void blk_dec_in_flight(BlockBackend *blk);
25
+
21
void blk_drain(BlockBackend *blk);
26
#endif
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
27
diff --git a/block/block-backend.c b/block/block-backend.c
25
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
26
--- a/block/block-backend.c
29
--- a/block/block-backend.c
27
+++ b/block/block-backend.c
30
+++ b/block/block-backend.c
28
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
31
@@ -XXX,XX +XXX,XX @@ const BdrvChild *blk_root(BlockBackend *blk)
29
return bdrv_make_zero(blk->root, flags);
32
{
33
return blk->root;
30
}
34
}
31
35
+
32
-static void blk_inc_in_flight(BlockBackend *blk)
36
+int blk_make_empty(BlockBackend *blk, Error **errp)
33
+void blk_inc_in_flight(BlockBackend *blk)
37
+{
34
{
38
+ if (!blk_is_available(blk)) {
35
atomic_inc(&blk->in_flight);
39
+ error_setg(errp, "No medium inserted");
36
}
40
+ return -ENOMEDIUM;
37
41
+ }
38
-static void blk_dec_in_flight(BlockBackend *blk)
42
+
39
+void blk_dec_in_flight(BlockBackend *blk)
43
+ return bdrv_make_empty(blk->root, errp);
40
{
44
+}
41
atomic_dec(&blk->in_flight);
42
aio_wait_kick();
43
--
45
--
44
2.20.1
46
2.25.4
45
47
46
48
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
If there's an error in commit_start() then the block job must be
3
bdrv_commit() already has a BlockBackend pointing to the BDS that we
4
deleted before replacing commit_top_bs, otherwise it will fail because
4
want to empty, it just has the wrong permissions.
5
of lack of permissions. This happens since the permission system was
6
introduced in 8dfba2797761d8a43744e4e6571c8175e448a478.
7
5
8
Fortunately this bug doesn't seem to be possible to reproduce at the
6
qemu-img commit has no BlockBackend pointing to the old backing file
9
moment without changing the code.
7
yet, but introducing one is simple.
10
8
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
After this commit, bdrv_make_empty() is the only remaining caller of
10
BlockDriver.bdrv_make_empty().
11
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200429141126.85159-5-mreitz@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
[kwolf: Fixed up reference output for 098]
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
17
---
14
block/commit.c | 4 +++-
18
block/commit.c | 16 +++++++++-------
15
1 file changed, 3 insertions(+), 1 deletion(-)
19
qemu-img.c | 19 ++++++++++++++-----
20
tests/qemu-iotests/098.out | 8 ++++----
21
3 files changed, 27 insertions(+), 16 deletions(-)
16
22
17
diff --git a/block/commit.c b/block/commit.c
23
diff --git a/block/commit.c b/block/commit.c
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/block/commit.c
25
--- a/block/commit.c
20
+++ b/block/commit.c
26
+++ b/block/commit.c
21
@@ -XXX,XX +XXX,XX @@ fail:
27
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
22
if (s->top) {
23
blk_unref(s->top);
24
}
28
}
25
+ job_early_fail(&s->common.job);
29
26
+ /* commit_top_bs has to be replaced after deleting the block job,
30
ctx = bdrv_get_aio_context(bs);
27
+ * otherwise this would fail because of lack of permissions. */
31
- src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
28
if (commit_top_bs) {
32
+ /* WRITE_UNCHANGED is required for bdrv_make_empty() */
29
bdrv_replace_node(commit_top_bs, top, &error_abort);
33
+ src = blk_new(ctx, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED,
34
+ BLK_PERM_ALL);
35
backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
36
37
ret = blk_insert_bs(src, bs, &local_err);
38
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
39
}
30
}
40
}
31
- job_early_fail(&s->common.job);
41
32
}
42
- if (drv->bdrv_make_empty) {
33
43
- ret = drv->bdrv_make_empty(bs);
34
44
- if (ret < 0) {
45
- goto ro_cleanup;
46
- }
47
- blk_flush(src);
48
+ ret = blk_make_empty(src, NULL);
49
+ /* Ignore -ENOTSUP */
50
+ if (ret < 0 && ret != -ENOTSUP) {
51
+ goto ro_cleanup;
52
}
53
54
+ blk_flush(src);
55
+
56
/*
57
* Make sure all data we wrote to the backing device is actually
58
* stable on disk.
59
diff --git a/qemu-img.c b/qemu-img.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/qemu-img.c
62
+++ b/qemu-img.c
63
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
64
goto unref_backing;
65
}
66
67
- if (!drop && bs->drv->bdrv_make_empty) {
68
- ret = bs->drv->bdrv_make_empty(bs);
69
- if (ret) {
70
- error_setg_errno(&local_err, -ret, "Could not empty %s",
71
- filename);
72
+ if (!drop) {
73
+ BlockBackend *old_backing_blk;
74
+
75
+ old_backing_blk = blk_new_with_bs(bs, BLK_PERM_WRITE, BLK_PERM_ALL,
76
+ &local_err);
77
+ if (!old_backing_blk) {
78
+ goto unref_backing;
79
+ }
80
+ ret = blk_make_empty(old_backing_blk, &local_err);
81
+ blk_unref(old_backing_blk);
82
+ if (ret == -ENOTSUP) {
83
+ error_free(local_err);
84
+ local_err = NULL;
85
+ } else if (ret < 0) {
86
goto unref_backing;
87
}
88
}
89
diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out
90
index XXXXXXX..XXXXXXX 100644
91
--- a/tests/qemu-iotests/098.out
92
+++ b/tests/qemu-iotests/098.out
93
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
94
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
95
wrote 65536/65536 bytes at offset 0
96
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
97
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
98
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
99
No errors were found on the image.
100
101
=== empty_image_prepare ===
102
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
103
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
104
wrote 65536/65536 bytes at offset 0
105
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
106
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
107
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
108
Leaked cluster 4 refcount=1 reference=0
109
Leaked cluster 5 refcount=1 reference=0
110
Repairing cluster 4 refcount=1 reference=0
111
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
112
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
113
wrote 65536/65536 bytes at offset 0
114
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
115
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
116
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
117
ERROR cluster 0 refcount=0 reference=1
118
ERROR cluster 1 refcount=0 reference=1
119
ERROR cluster 3 refcount=0 reference=1
120
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
121
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
122
wrote 65536/65536 bytes at offset 0
123
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
124
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
125
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
126
ERROR cluster 0 refcount=0 reference=1
127
ERROR cluster 1 refcount=0 reference=1
128
ERROR cluster 3 refcount=0 reference=1
35
--
129
--
36
2.20.1
130
2.25.4
37
131
38
132
diff view generated by jsdifflib
1
virtio_blk_dma_restart_bh() submits new requests, so in order to make
1
This is just a bandaid to keep tests/test-replication working after
2
sure that these requests are not started inside a drained section of the
2
bdrv_make_empty() starts to assert that we're not trying to call it on a
3
attached BlockBackend, we need to make sure that draining the
3
read-only child.
4
BlockBackend waits for the BH to be executed.
5
4
6
This BH is still questionable because its scheduled in the main thread
5
For the real solution in the future, replication should not steal the
7
instead of the configured iothread. Leave a FIXME comment for this.
6
BdrvChild from its backing file (this is never correct to do!), but
8
7
instead have its own child node references, with the appropriate
9
But with this fix, enabling the data plane at least waits for these
8
permissions.
10
requests (in bdrv_set_aio_context()) instead of changing the AioContext
11
under their feet and making them run in the wrong thread, causing
12
crashes and failures (e.g. due to missing locking).
13
9
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/replication.c | 13 +++++++++++--
17
1 file changed, 4 insertions(+)
13
1 file changed, 11 insertions(+), 2 deletions(-)
18
14
19
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
15
diff --git a/block/replication.c b/block/replication.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/block/virtio-blk.c
17
--- a/block/replication.c
22
+++ b/hw/block/virtio-blk.c
18
+++ b/block/replication.c
23
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
19
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
24
if (mrb.num_reqs) {
20
return;
25
virtio_blk_submit_multireq(s->blk, &mrb);
26
}
21
}
27
+ blk_dec_in_flight(s->conf.conf.blk);
22
28
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
23
- ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs);
29
}
24
+ BlockBackend *blk = blk_new(qemu_get_current_aio_context(),
30
25
+ BLK_PERM_WRITE, BLK_PERM_ALL);
31
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
26
+ blk_insert_bs(blk, s->hidden_disk->bs, &local_err);
32
}
27
+ if (local_err) {
33
28
+ error_propagate(errp, local_err);
34
if (!s->bh) {
29
+ blk_unref(blk);
35
+ /* FIXME The data plane is not started yet, so these requests are
30
+ return;
36
+ * processed in the main thread. */
31
+ }
37
s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
32
+
38
virtio_blk_dma_restart_bh, s);
33
+ ret = blk_make_empty(blk, errp);
39
+ blk_inc_in_flight(s->conf.conf.blk);
34
+ blk_unref(blk);
40
qemu_bh_schedule(s->bh);
35
if (ret < 0) {
36
- error_setg(errp, "Cannot make hidden disk empty");
37
return;
41
}
38
}
42
}
39
}
43
--
40
--
44
2.20.1
41
2.25.4
45
42
46
43
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
3
This test creates no such file.
4
2
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Message-id: 20190210145736.1486-4-mreitz@redhat.com
6
Message-Id: <20200429141126.85159-3-mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
8
---
11
tests/qemu-iotests/232 | 1 -
9
block/replication.c | 3 +--
12
1 file changed, 1 deletion(-)
10
block/vvfat.c | 4 +---
11
2 files changed, 2 insertions(+), 5 deletions(-)
13
12
14
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
13
diff --git a/block/replication.c b/block/replication.c
15
index XXXXXXX..XXXXXXX 100755
14
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/232
15
--- a/block/replication.c
17
+++ b/tests/qemu-iotests/232
16
+++ b/block/replication.c
18
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
17
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
19
_cleanup()
18
return;
20
{
19
}
21
_cleanup_test_img
20
22
- rm -f $TEST_IMG.snap
21
- ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs);
23
}
22
+ ret = bdrv_make_empty(s->active_disk, errp);
24
trap "_cleanup; exit \$status" 0 1 2 3 15
23
if (ret < 0) {
24
- error_setg(errp, "Cannot make active disk empty");
25
return;
26
}
27
28
diff --git a/block/vvfat.c b/block/vvfat.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/vvfat.c
31
+++ b/block/vvfat.c
32
@@ -XXX,XX +XXX,XX @@ static int do_commit(BDRVVVFATState* s)
33
return ret;
34
}
35
36
- if (s->qcow->bs->drv && s->qcow->bs->drv->bdrv_make_empty) {
37
- s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
38
- }
39
+ bdrv_make_empty(s->qcow, NULL);
40
41
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
25
42
26
--
43
--
27
2.20.1
44
2.25.4
28
45
29
46
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
VDI keeps the whole bitmap in memory, and the maximum size (which is
3
The commit, mirror, and blkreplay block nodes are filters, so they should
4
tested here) is 2 GB. This may not be available on all machines, and it
4
be marked as such.
5
rarely is available when running a 32 bit build.
6
7
Fix this by making VM.run_job() return the error string if an error
8
occurred, and checking whether that contains "Could not allocate bmap"
9
in 211. If so, the test is skipped.
10
5
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20190218180646.30282-1-mreitz@redhat.com
7
Message-Id: <20200513110544.176672-2-mreitz@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
9
---
17
tests/qemu-iotests/211 | 4 +++-
10
block/blkreplay.c | 1 +
18
tests/qemu-iotests/iotests.py | 5 ++++-
11
block/commit.c | 2 ++
19
2 files changed, 7 insertions(+), 2 deletions(-)
12
block/mirror.c | 2 ++
13
3 files changed, 5 insertions(+)
20
14
21
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
15
diff --git a/block/blkreplay.c b/block/blkreplay.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
16
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/iotests.py
17
--- a/block/blkreplay.c
39
+++ b/tests/qemu-iotests/iotests.py
18
+++ b/block/blkreplay.c
40
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
19
@@ -XXX,XX +XXX,XX @@ static int blkreplay_snapshot_goto(BlockDriverState *bs,
41
log(result, filters, indent=indent)
20
static BlockDriver bdrv_blkreplay = {
42
return result
21
.format_name = "blkreplay",
43
22
.instance_size = 0,
44
+ # Returns None on success, and an error string on failure
23
+ .is_filter = true,
45
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
24
46
+ error = None
25
.bdrv_open = blkreplay_open,
47
while True:
26
.bdrv_child_perm = bdrv_filter_default_perms,
48
for ev in self.get_qmp_events_filtered(wait=True):
27
diff --git a/block/commit.c b/block/commit.c
49
if ev['event'] == 'JOB_STATUS_CHANGE':
28
index XXXXXXX..XXXXXXX 100644
50
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
29
--- a/block/commit.c
51
result = self.qmp('query-jobs')
30
+++ b/block/commit.c
52
for j in result['return']:
31
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_commit_top = {
53
if j['id'] == job:
32
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
54
+ error = j['error']
33
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
55
log('Job failed: %s' % (j['error']))
34
.bdrv_child_perm = bdrv_commit_top_child_perm,
56
elif status == 'pending' and not auto_finalize:
35
+
57
self.qmp_log('job-finalize', id=job)
36
+ .is_filter = true,
58
elif status == 'concluded' and not auto_dismiss:
37
};
59
self.qmp_log('job-dismiss', id=job)
38
60
elif status == 'null':
39
void commit_start(const char *job_id, BlockDriverState *bs,
61
- return
40
diff --git a/block/mirror.c b/block/mirror.c
62
+ return error
41
index XXXXXXX..XXXXXXX 100644
63
else:
42
--- a/block/mirror.c
64
iotests.log(ev)
43
+++ b/block/mirror.c
65
44
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
45
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
46
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
47
.bdrv_child_perm = bdrv_mirror_top_child_perm,
48
+
49
+ .is_filter = true,
50
};
51
52
static BlockJob *mirror_start_job(
66
--
53
--
67
2.20.1
54
2.25.4
68
55
69
56
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
If the backing file is overridden, this most probably does change the
3
We want to unify child_format and child_file at some point. One of the
4
guest-visible data of a BDS. Therefore, we will need to consider this
4
important things that set format drivers apart from other drivers is
5
in bdrv_refresh_filename().
5
that they do not expect other format nodes under them (except in the
6
6
backing chain), i.e. we must not probe formats inside of formats. That
7
To see whether it has been overridden, we might want to compare
7
means we need something on which to distinguish format drivers from
8
bs->backing_file and bs->backing->bs->filename. However,
8
others, and hence this flag.
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
9
58
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
59
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
60
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Alberto Garcia <berto@igalia.com>
61
Message-id: 20190201192935.18394-5-mreitz@redhat.com
13
Message-Id: <20200513110544.176672-3-mreitz@redhat.com>
62
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
63
---
15
---
64
include/block/block_int.h | 4 ++++
16
include/block/block_int.h | 7 +++++++
65
block.c | 19 +++++++++++++++++++
17
block/bochs.c | 1 +
66
block/qcow.c | 7 +++++--
18
block/cloop.c | 1 +
67
block/qcow2.c | 10 +++++++---
19
block/crypto.c | 2 ++
68
block/qed.c | 7 +++++--
20
block/dmg.c | 1 +
69
block/vmdk.c | 6 ++++--
21
block/parallels.c | 1 +
70
6 files changed, 44 insertions(+), 9 deletions(-)
22
block/qcow.c | 1 +
23
block/qcow2.c | 1 +
24
block/qed.c | 1 +
25
block/raw-format.c | 1 +
26
block/vdi.c | 1 +
27
block/vhdx.c | 1 +
28
block/vmdk.c | 1 +
29
block/vpc.c | 1 +
30
14 files changed, 21 insertions(+)
71
31
72
diff --git a/include/block/block_int.h b/include/block/block_int.h
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
73
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
74
--- a/include/block/block_int.h
34
--- a/include/block/block_int.h
75
+++ b/include/block/block_int.h
35
+++ b/include/block/block_int.h
76
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
77
char filename[PATH_MAX];
37
* must implement them and return -ENOTSUP.
78
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
38
*/
79
this file image */
39
bool is_filter;
80
+ /* The backing filename indicated by the image header; if we ever
40
+ /*
81
+ * open this file, then this is replaced by the resulting BDS's
41
+ * Set to true if the BlockDriver is a format driver. Format nodes
82
+ * filename (i.e. after a bdrv_refresh_filename() run). */
42
+ * generally do not expect their children to be other format nodes
83
+ char auto_backing_file[PATH_MAX];
43
+ * (except for backing files), and so format probing is disabled
84
char backing_format[16]; /* if non-zero and backing_file exists */
44
+ * on those children.
85
45
+ */
86
QDict *full_open_options;
46
+ bool is_format;
87
diff --git a/block.c b/block.c
47
/*
88
index XXXXXXX..XXXXXXX 100644
48
* Return true if @to_replace can be replaced by a BDS with the
89
--- a/block.c
49
* same data as @bs without it affecting @bs's behavior (that is,
90
+++ b/block.c
50
diff --git a/block/bochs.c b/block/bochs.c
91
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
51
index XXXXXXX..XXXXXXX 100644
92
char *bdref_key_dot;
52
--- a/block/bochs.c
93
const char *reference = NULL;
53
+++ b/block/bochs.c
94
int ret = 0;
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_bochs = {
95
+ bool implicit_backing = false;
55
.bdrv_refresh_limits = bochs_refresh_limits,
96
BlockDriverState *backing_hd;
56
.bdrv_co_preadv = bochs_co_preadv,
97
QDict *options;
57
.bdrv_close        = bochs_close,
98
QDict *tmp_parent_options = NULL;
58
+ .is_format = true,
99
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
59
};
100
qobject_unref(options);
60
101
goto free_exit;
61
static void bdrv_bochs_init(void)
102
} else {
62
diff --git a/block/cloop.c b/block/cloop.c
103
+ if (qdict_size(options) == 0) {
63
index XXXXXXX..XXXXXXX 100644
104
+ /* If the user specifies options that do not modify the
64
--- a/block/cloop.c
105
+ * backing file's behavior, we might still consider it the
65
+++ b/block/cloop.c
106
+ * implicit backing file. But it's easier this way, and
66
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_cloop = {
107
+ * just specifying some of the backing BDS's options is
67
.bdrv_refresh_limits = cloop_refresh_limits,
108
+ * only possible with -drive anyway (otherwise the QAPI
68
.bdrv_co_preadv = cloop_co_preadv,
109
+ * schema forces the user to specify everything). */
69
.bdrv_close = cloop_close,
110
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
70
+ .is_format = true,
111
+ }
71
};
72
73
static void bdrv_cloop_init(void)
74
diff --git a/block/crypto.c b/block/crypto.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/crypto.c
77
+++ b/block/crypto.c
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
79
.bdrv_get_info = block_crypto_get_info_luks,
80
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
81
82
+ .is_format = true,
112
+
83
+
113
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
84
.strong_runtime_opts = block_crypto_strong_runtime_opts,
114
&local_err);
85
};
115
if (local_err) {
86
116
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
87
diff --git a/block/dmg.c b/block/dmg.c
117
}
88
index XXXXXXX..XXXXXXX 100644
118
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
89
--- a/block/dmg.c
119
90
+++ b/block/dmg.c
120
+ if (implicit_backing) {
91
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_dmg = {
121
+ bdrv_refresh_filename(backing_hd);
92
.bdrv_child_perm = bdrv_format_default_perms,
122
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
93
.bdrv_co_preadv = dmg_co_preadv,
123
+ backing_hd->filename);
94
.bdrv_close = dmg_close,
124
+ }
95
+ .is_format = true,
125
+
96
};
126
/* Hook up the backing file link; drop our reference, bs owns the
97
127
* backing_hd reference now */
98
static void bdrv_dmg_init(void)
128
bdrv_set_backing_hd(bs, backing_hd, &local_err);
99
diff --git a/block/parallels.c b/block/parallels.c
129
@@ -XXX,XX +XXX,XX @@ int bdrv_change_backing_file(BlockDriverState *bs,
100
index XXXXXXX..XXXXXXX 100644
130
if (ret == 0) {
101
--- a/block/parallels.c
131
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
102
+++ b/block/parallels.c
132
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
103
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
133
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
104
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
134
+ backing_file ?: "");
105
.bdrv_co_readv = parallels_co_readv,
135
}
106
.bdrv_co_writev = parallels_co_writev,
136
return ret;
107
+ .is_format = true,
137
}
108
.supports_backing = true,
109
.bdrv_co_create = parallels_co_create,
110
.bdrv_co_create_opts = parallels_co_create_opts,
138
diff --git a/block/qcow.c b/block/qcow.c
111
diff --git a/block/qcow.c b/block/qcow.c
139
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
140
--- a/block/qcow.c
113
--- a/block/qcow.c
141
+++ b/block/qcow.c
114
+++ b/block/qcow.c
142
@@ -XXX,XX +XXX,XX @@
115
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
143
#include "qemu/module.h"
116
.bdrv_co_create = qcow_co_create,
144
#include "qemu/option.h"
117
.bdrv_co_create_opts = qcow_co_create_opts,
145
#include "qemu/bswap.h"
118
.bdrv_has_zero_init = bdrv_has_zero_init_1,
146
+#include "qemu/cutils.h"
119
+ .is_format = true,
147
#include <zlib.h>
120
.supports_backing = true,
148
#include "qapi/qmp/qdict.h"
121
.bdrv_refresh_limits = qcow_refresh_limits,
149
#include "qapi/qmp/qstring.h"
122
150
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
151
goto fail;
152
}
153
ret = bdrv_pread(bs->file, header.backing_file_offset,
154
- bs->backing_file, len);
155
+ bs->auto_backing_file, len);
156
if (ret < 0) {
157
goto fail;
158
}
159
- bs->backing_file[len] = '\0';
160
+ bs->auto_backing_file[len] = '\0';
161
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
162
+ bs->auto_backing_file);
163
}
164
165
/* Disable migration when qcow images are used */
166
diff --git a/block/qcow2.c b/block/qcow2.c
123
diff --git a/block/qcow2.c b/block/qcow2.c
167
index XXXXXXX..XXXXXXX 100644
124
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
125
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
126
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
127
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
171
goto fail;
128
.bdrv_save_vmstate = qcow2_save_vmstate,
172
}
129
.bdrv_load_vmstate = qcow2_load_vmstate,
173
ret = bdrv_pread(bs->file, header.backing_file_offset,
130
174
- bs->backing_file, len);
131
+ .is_format = true,
175
+ bs->auto_backing_file, len);
132
.supports_backing = true,
176
if (ret < 0) {
133
.bdrv_change_backing_file = qcow2_change_backing_file,
177
error_setg_errno(errp, -ret, "Could not read backing file name");
178
goto fail;
179
}
180
- bs->backing_file[len] = '\0';
181
- s->image_backing_file = g_strdup(bs->backing_file);
182
+ bs->auto_backing_file[len] = '\0';
183
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
184
+ bs->auto_backing_file);
185
+ s->image_backing_file = g_strdup(bs->auto_backing_file);
186
}
187
188
/* Internal snapshots */
189
@@ -XXX,XX +XXX,XX @@ static int qcow2_change_backing_file(BlockDriverState *bs,
190
return -EINVAL;
191
}
192
193
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
194
+ backing_file ?: "");
195
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
196
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
197
134
198
diff --git a/block/qed.c b/block/qed.c
135
diff --git a/block/qed.c b/block/qed.c
199
index XXXXXXX..XXXXXXX 100644
136
index XXXXXXX..XXXXXXX 100644
200
--- a/block/qed.c
137
--- a/block/qed.c
201
+++ b/block/qed.c
138
+++ b/block/qed.c
202
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
139
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
203
}
140
.format_name = "qed",
204
141
.instance_size = sizeof(BDRVQEDState),
205
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
142
.create_opts = &qed_create_opts,
206
- s->header.backing_filename_size, bs->backing_file,
143
+ .is_format = true,
207
- sizeof(bs->backing_file));
144
.supports_backing = true,
208
+ s->header.backing_filename_size,
145
209
+ bs->auto_backing_file,
146
.bdrv_probe = bdrv_qed_probe,
210
+ sizeof(bs->auto_backing_file));
147
diff --git a/block/raw-format.c b/block/raw-format.c
211
if (ret < 0) {
148
index XXXXXXX..XXXXXXX 100644
212
return ret;
149
--- a/block/raw-format.c
213
}
150
+++ b/block/raw-format.c
214
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
151
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
215
+ bs->auto_backing_file);
152
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
216
153
.bdrv_co_truncate = &raw_co_truncate,
217
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
154
.bdrv_getlength = &raw_getlength,
218
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
155
+ .is_format = true,
156
.has_variable_length = true,
157
.bdrv_measure = &raw_measure,
158
.bdrv_get_info = &raw_get_info,
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
164
165
.bdrv_get_info = vdi_get_info,
166
167
+ .is_format = true,
168
.create_opts = &vdi_create_opts,
169
.bdrv_co_check = vdi_co_check,
170
};
171
diff --git a/block/vhdx.c b/block/vhdx.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/block/vhdx.c
174
+++ b/block/vhdx.c
175
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
176
.bdrv_co_check = vhdx_co_check,
177
.bdrv_has_zero_init = vhdx_has_zero_init,
178
179
+ .is_format = true,
180
.create_opts = &vhdx_create_opts,
181
};
182
219
diff --git a/block/vmdk.c b/block/vmdk.c
183
diff --git a/block/vmdk.c b/block/vmdk.c
220
index XXXXXXX..XXXXXXX 100644
184
index XXXXXXX..XXXXXXX 100644
221
--- a/block/vmdk.c
185
--- a/block/vmdk.c
222
+++ b/block/vmdk.c
186
+++ b/block/vmdk.c
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
187
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
224
ret = -EINVAL;
188
.bdrv_get_info = vmdk_get_info,
225
goto out;
189
.bdrv_gather_child_options = vmdk_gather_child_options,
226
}
190
227
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
191
+ .is_format = true,
228
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
192
.supports_backing = true,
229
ret = -EINVAL;
193
.create_opts = &vmdk_create_opts,
230
goto out;
194
};
231
}
195
diff --git a/block/vpc.c b/block/vpc.c
232
196
index XXXXXXX..XXXXXXX 100644
233
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
197
--- a/block/vpc.c
234
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
198
+++ b/block/vpc.c
235
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
236
+ bs->auto_backing_file);
200
237
}
201
.bdrv_get_info = vpc_get_info,
238
202
239
out:
203
+ .is_format = true,
204
.create_opts = &vpc_create_opts,
205
.bdrv_has_zero_init = vpc_has_zero_init,
206
.strong_runtime_opts = vpc_strong_runtime_opts,
240
--
207
--
241
2.20.1
208
2.25.4
242
209
243
210
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
bdrv_refresh_filename() should invoke itself recursively on all
3
This structure nearly only contains parent callbacks for child state
4
children, not just on file.
4
changes. It cannot really reflect a child's role, because different
5
5
roles may overlap (as we will see when real roles are introduced), and
6
With that change, we can remove the manual invocations in blkverify,
6
because parents can have custom callbacks even when the child fulfills a
7
quorum, commit, mirror, and blklogwrites.
7
standard role.
8
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20190201192935.18394-3-mreitz@redhat.com
12
Message-Id: <20200513110544.176672-4-mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
14
---
15
block.c | 9 +++++----
15
include/block/block.h | 6 +-
16
block/blklogwrites.c | 3 ---
16
include/block/block_int.h | 22 +++---
17
block/blkverify.c | 3 ---
17
block.c | 142 ++++++++++++++++++------------------
18
block/commit.c | 1 -
18
block/backup-top.c | 8 +-
19
block/mirror.c | 1 -
19
block/blkdebug.c | 4 +-
20
block/quorum.c | 1 -
20
block/blklogwrites.c | 8 +-
21
6 files changed, 5 insertions(+), 13 deletions(-)
21
block/block-backend.c | 6 +-
22
block/commit.c | 2 +-
23
block/copy-on-read.c | 2 +-
24
block/io.c | 22 +++---
25
block/mirror.c | 2 +-
26
block/quorum.c | 2 +-
27
block/replication.c | 2 +-
28
block/vvfat.c | 6 +-
29
blockjob.c | 2 +-
30
tests/test-bdrv-drain.c | 36 ++++-----
31
tests/test-bdrv-graph-mod.c | 2 +-
32
17 files changed, 141 insertions(+), 133 deletions(-)
22
33
34
diff --git a/include/block/block.h b/include/block/block.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block.h
37
+++ b/include/block/block.h
38
@@ -XXX,XX +XXX,XX @@
39
/* block.c */
40
typedef struct BlockDriver BlockDriver;
41
typedef struct BdrvChild BdrvChild;
42
-typedef struct BdrvChildRole BdrvChildRole;
43
+typedef struct BdrvChildClass BdrvChildClass;
44
45
typedef struct BlockDriverInfo {
46
/* in bytes, 0 if irrelevant */
47
@@ -XXX,XX +XXX,XX @@ int bdrv_parse_discard_flags(const char *mode, int *flags);
48
BdrvChild *bdrv_open_child(const char *filename,
49
QDict *options, const char *bdref_key,
50
BlockDriverState* parent,
51
- const BdrvChildRole *child_role,
52
+ const BdrvChildClass *child_class,
53
bool allow_none, Error **errp);
54
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
55
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
56
@@ -XXX,XX +XXX,XX @@ void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
57
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
58
BlockDriverState *child_bs,
59
const char *child_name,
60
- const BdrvChildRole *child_role,
61
+ const BdrvChildClass *child_class,
62
Error **errp);
63
64
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
65
diff --git a/include/block/block_int.h b/include/block/block_int.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/block_int.h
68
+++ b/include/block/block_int.h
69
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
70
* the parents in @parent_perm and @parent_shared.
71
*
72
* If @c is NULL, return the permissions for attaching a new child for the
73
- * given @role.
74
+ * given @child_class.
75
*
76
* If @reopen_queue is non-NULL, don't return the currently needed
77
* permissions, but those that will be needed after applying the
78
* @reopen_queue.
79
*/
80
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
81
- const BdrvChildRole *role,
82
+ const BdrvChildClass *child_class,
83
BlockReopenQueue *reopen_queue,
84
uint64_t parent_perm, uint64_t parent_shared,
85
uint64_t *nperm, uint64_t *nshared);
86
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvAioNotifier {
87
QLIST_ENTRY(BdrvAioNotifier) list;
88
} BdrvAioNotifier;
89
90
-struct BdrvChildRole {
91
+struct BdrvChildClass {
92
/* If true, bdrv_replace_node() doesn't change the node this BdrvChild
93
* points to. */
94
bool stay_at_node;
95
@@ -XXX,XX +XXX,XX @@ struct BdrvChildRole {
96
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
97
};
98
99
-extern const BdrvChildRole child_file;
100
-extern const BdrvChildRole child_format;
101
-extern const BdrvChildRole child_backing;
102
+extern const BdrvChildClass child_file;
103
+extern const BdrvChildClass child_format;
104
+extern const BdrvChildClass child_backing;
105
106
struct BdrvChild {
107
BlockDriverState *bs;
108
char *name;
109
- const BdrvChildRole *role;
110
+ const BdrvChildClass *klass;
111
void *opaque;
112
113
/**
114
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
115
116
/*
117
* How many times the parent of this child has been drained
118
- * (through role->drained_*).
119
+ * (through klass->drained_*).
120
* Usually, this is equal to bs->quiesce_counter (potentially
121
* reduced by bdrv_drain_all_count). It may differ while the
122
* child is entering or leaving a drained section.
123
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
124
125
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
126
const char *child_name,
127
- const BdrvChildRole *child_role,
128
+ const BdrvChildClass *child_class,
129
AioContext *ctx,
130
uint64_t perm, uint64_t shared_perm,
131
void *opaque, Error **errp);
132
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
133
* block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to
134
* all children */
135
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
136
- const BdrvChildRole *role,
137
+ const BdrvChildClass *child_class,
138
BlockReopenQueue *reopen_queue,
139
uint64_t perm, uint64_t shared,
140
uint64_t *nperm, uint64_t *nshared);
141
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
142
* requires WRITE | RESIZE for read-write images, always requires
143
* CONSISTENT_READ and doesn't share WRITE. */
144
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
145
- const BdrvChildRole *role,
146
+ const BdrvChildClass *child_class,
147
BlockReopenQueue *reopen_queue,
148
uint64_t perm, uint64_t shared,
149
uint64_t *nperm, uint64_t *nshared);
23
diff --git a/block.c b/block.c
150
diff --git a/block.c b/block.c
24
index XXXXXXX..XXXXXXX 100644
151
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
152
--- a/block.c
26
+++ b/block.c
153
+++ b/block.c
27
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
154
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
28
void bdrv_refresh_filename(BlockDriverState *bs)
155
const char *reference,
29
{
156
QDict *options, int flags,
30
BlockDriver *drv = bs->drv;
157
BlockDriverState *parent,
31
+ BdrvChild *child;
158
- const BdrvChildRole *child_role,
32
QDict *opts;
159
+ const BdrvChildClass *child_class,
33
160
Error **errp);
34
if (!drv) {
161
162
/* If non-zero, use only whitelisted block drivers */
163
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
164
*child_flags = flags;
165
}
166
167
-const BdrvChildRole child_file = {
168
+const BdrvChildClass child_file = {
169
.parent_is_bds = true,
170
.get_parent_desc = bdrv_child_get_parent_desc,
171
.inherit_options = bdrv_inherited_options,
172
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
173
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
174
}
175
176
-const BdrvChildRole child_format = {
177
+const BdrvChildClass child_format = {
178
.parent_is_bds = true,
179
.get_parent_desc = bdrv_child_get_parent_desc,
180
.inherit_options = bdrv_inherited_fmt_options,
181
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
182
return ret;
183
}
184
185
-const BdrvChildRole child_backing = {
186
+const BdrvChildClass child_backing = {
187
.parent_is_bds = true,
188
.get_parent_desc = bdrv_child_get_parent_desc,
189
.attach = bdrv_backing_attach,
190
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
191
}
192
193
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
194
- BdrvChild *c, const BdrvChildRole *role,
195
+ BdrvChild *c, const BdrvChildClass *child_class,
196
BlockReopenQueue *reopen_queue,
197
uint64_t parent_perm, uint64_t parent_shared,
198
uint64_t *nperm, uint64_t *nshared)
199
{
200
assert(bs->drv && bs->drv->bdrv_child_perm);
201
- bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
202
+ bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue,
203
parent_perm, parent_shared,
204
nperm, nshared);
205
/* TODO Take force_share from reopen_queue */
206
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
207
uint64_t cur_perm, cur_shared;
208
bool child_tighten_restr;
209
210
- bdrv_child_perm(bs, c->bs, c, c->role, q,
211
+ bdrv_child_perm(bs, c->bs, c, c->klass, q,
212
cumulative_perms, cumulative_shared_perms,
213
&cur_perm, &cur_shared);
214
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
215
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
216
/* Update all children */
217
QLIST_FOREACH(c, &bs->children, next) {
218
uint64_t cur_perm, cur_shared;
219
- bdrv_child_perm(bs, c->bs, c, c->role, NULL,
220
+ bdrv_child_perm(bs, c->bs, c, c->klass, NULL,
221
cumulative_perms, cumulative_shared_perms,
222
&cur_perm, &cur_shared);
223
bdrv_child_set_perm(c, cur_perm, cur_shared);
224
@@ -XXX,XX +XXX,XX @@ void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm,
225
226
static char *bdrv_child_user_desc(BdrvChild *c)
227
{
228
- if (c->role->get_parent_desc) {
229
- return c->role->get_parent_desc(c);
230
+ if (c->klass->get_parent_desc) {
231
+ return c->klass->get_parent_desc(c);
232
}
233
234
return g_strdup("another user");
235
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
236
uint64_t perms, shared;
237
238
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
239
- bdrv_child_perm(bs, c->bs, c, c->role, NULL, parent_perms, parent_shared,
240
+ bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared,
241
&perms, &shared);
242
243
return bdrv_child_try_set_perm(c, perms, shared, errp);
244
}
245
246
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
247
- const BdrvChildRole *role,
248
+ const BdrvChildClass *child_class,
249
BlockReopenQueue *reopen_queue,
250
uint64_t perm, uint64_t shared,
251
uint64_t *nperm, uint64_t *nshared)
252
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
253
}
254
255
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
256
- const BdrvChildRole *role,
257
+ const BdrvChildClass *child_class,
258
BlockReopenQueue *reopen_queue,
259
uint64_t perm, uint64_t shared,
260
uint64_t *nperm, uint64_t *nshared)
261
{
262
- bool backing = (role == &child_backing);
263
- assert(role == &child_backing || role == &child_file);
264
+ bool backing = (child_class == &child_backing);
265
+ assert(child_class == &child_backing || child_class == &child_file);
266
267
if (!backing) {
268
int flags = bdrv_reopen_get_flags(reopen_queue, bs);
269
270
/* Apart from the modifications below, the same permissions are
271
* forwarded and left alone as for filters */
272
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
273
- &perm, &shared);
274
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
275
+ perm, shared, &perm, &shared);
276
277
/* Format drivers may touch metadata even if the guest doesn't write */
278
if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
279
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
280
* If the new child node is drained but the old one was not, flush
281
* all outstanding requests to the old child node.
282
*/
283
- while (drain_saldo > 0 && child->role->drained_begin) {
284
+ while (drain_saldo > 0 && child->klass->drained_begin) {
285
bdrv_parent_drained_begin_single(child, true);
286
drain_saldo--;
287
}
288
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
289
/* Detach first so that the recursive drain sections coming from @child
290
* are already gone and we only end the drain sections that came from
291
* elsewhere. */
292
- if (child->role->detach) {
293
- child->role->detach(child);
294
+ if (child->klass->detach) {
295
+ child->klass->detach(child);
296
}
297
QLIST_REMOVE(child, next_parent);
298
}
299
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
300
/* Attach only after starting new drained sections, so that recursive
301
* drain sections coming from @child don't get an extra .drained_begin
302
* callback. */
303
- if (child->role->attach) {
304
- child->role->attach(child);
305
+ if (child->klass->attach) {
306
+ child->klass->attach(child);
307
}
308
}
309
310
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild *child,
311
* If the old child node was drained but the new one is not, allow
312
* requests to come in only after the new node has been attached.
313
*/
314
- while (drain_saldo < 0 && child->role->drained_end) {
315
+ while (drain_saldo < 0 && child->klass->drained_end) {
316
bdrv_parent_drained_end_single(child);
317
drain_saldo++;
318
}
319
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
320
*/
321
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
322
const char *child_name,
323
- const BdrvChildRole *child_role,
324
+ const BdrvChildClass *child_class,
325
AioContext *ctx,
326
uint64_t perm, uint64_t shared_perm,
327
void *opaque, Error **errp)
328
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
329
*child = (BdrvChild) {
330
.bs = NULL,
331
.name = g_strdup(child_name),
332
- .role = child_role,
333
+ .klass = child_class,
334
.perm = perm,
335
.shared_perm = shared_perm,
336
.opaque = opaque,
337
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
338
* try moving the parent into the AioContext of child_bs instead. */
339
if (bdrv_get_aio_context(child_bs) != ctx) {
340
ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
341
- if (ret < 0 && child_role->can_set_aio_ctx) {
342
+ if (ret < 0 && child_class->can_set_aio_ctx) {
343
GSList *ignore = g_slist_prepend(NULL, child);
344
ctx = bdrv_get_aio_context(child_bs);
345
- if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
346
+ if (child_class->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
347
error_free(local_err);
348
ret = 0;
349
g_slist_free(ignore);
350
ignore = g_slist_prepend(NULL, child);
351
- child_role->set_aio_ctx(child, ctx, &ignore);
352
+ child_class->set_aio_ctx(child, ctx, &ignore);
353
}
354
g_slist_free(ignore);
355
}
356
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
357
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
358
BlockDriverState *child_bs,
359
const char *child_name,
360
- const BdrvChildRole *child_role,
361
+ const BdrvChildClass *child_class,
362
Error **errp)
363
{
364
BdrvChild *child;
365
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
366
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
367
368
assert(parent_bs->drv);
369
- bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
370
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL,
371
perm, shared_perm, &perm, &shared_perm);
372
373
- child = bdrv_root_attach_child(child_bs, child_name, child_role,
374
+ child = bdrv_root_attach_child(child_bs, child_name, child_class,
375
bdrv_get_aio_context(parent_bs),
376
perm, shared_perm, parent_bs, errp);
377
if (child == NULL) {
378
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_change_media(BlockDriverState *bs, bool load)
379
{
380
BdrvChild *c;
381
QLIST_FOREACH(c, &bs->parents, next_parent) {
382
- if (c->role->change_media) {
383
- c->role->change_media(c, load);
384
+ if (c->klass->change_media) {
385
+ c->klass->change_media(c, load);
386
}
387
}
388
}
389
@@ -XXX,XX +XXX,XX @@ free_exit:
390
391
static BlockDriverState *
392
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
393
- BlockDriverState *parent, const BdrvChildRole *child_role,
394
+ BlockDriverState *parent, const BdrvChildClass *child_class,
395
bool allow_none, Error **errp)
396
{
397
BlockDriverState *bs = NULL;
398
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
399
char *bdref_key_dot;
400
const char *reference;
401
402
- assert(child_role != NULL);
403
+ assert(child_class != NULL);
404
405
bdref_key_dot = g_strdup_printf("%s.", bdref_key);
406
qdict_extract_subqdict(options, &image_options, bdref_key_dot);
407
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
408
}
409
410
bs = bdrv_open_inherit(filename, reference, image_options, 0,
411
- parent, child_role, errp);
412
+ parent, child_class, errp);
413
if (!bs) {
414
goto done;
415
}
416
@@ -XXX,XX +XXX,XX @@ done:
417
BdrvChild *bdrv_open_child(const char *filename,
418
QDict *options, const char *bdref_key,
419
BlockDriverState *parent,
420
- const BdrvChildRole *child_role,
421
+ const BdrvChildClass *child_class,
422
bool allow_none, Error **errp)
423
{
424
BlockDriverState *bs;
425
426
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role,
427
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
428
allow_none, errp);
429
if (bs == NULL) {
430
return NULL;
431
}
432
433
- return bdrv_attach_child(parent, bs, bdref_key, child_role, errp);
434
+ return bdrv_attach_child(parent, bs, bdref_key, child_class, errp);
435
}
436
437
-/* TODO Future callers may need to specify parent/child_role in order for
438
- * option inheritance to work. Existing callers use it for the root node. */
439
+/*
440
+ * TODO Future callers may need to specify parent/child_class in order for
441
+ * option inheritance to work. Existing callers use it for the root node.
442
+ */
443
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
444
{
445
BlockDriverState *bs = NULL;
446
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
447
const char *reference,
448
QDict *options, int flags,
449
BlockDriverState *parent,
450
- const BdrvChildRole *child_role,
451
+ const BdrvChildClass *child_class,
452
Error **errp)
453
{
454
int ret;
455
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
456
QDict *snapshot_options = NULL;
457
int snapshot_flags = 0;
458
459
- assert(!child_role || !flags);
460
- assert(!child_role == !parent);
461
+ assert(!child_class || !flags);
462
+ assert(!child_class == !parent);
463
464
if (reference) {
465
bool options_non_empty = options ? qdict_size(options) : false;
466
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
467
468
bs->explicit_options = qdict_clone_shallow(options);
469
470
- if (child_role) {
471
+ if (child_class) {
472
bs->inherits_from = parent;
473
- child_role->inherit_options(&flags, options,
474
- parent->open_flags, parent->options);
475
+ child_class->inherit_options(&flags, options,
476
+ parent->open_flags, parent->options);
477
}
478
479
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
480
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
481
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
482
BlockDriverState *bs,
483
QDict *options,
484
- const BdrvChildRole *role,
485
+ const BdrvChildClass *klass,
486
QDict *parent_options,
487
int parent_flags,
488
bool keep_old_opts)
489
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
490
/* Inherit from parent node */
491
if (parent_options) {
492
flags = 0;
493
- role->inherit_options(&flags, options, parent_flags, parent_options);
494
+ klass->inherit_options(&flags, options, parent_flags, parent_options);
495
} else {
496
flags = bdrv_get_flags(bs);
497
}
498
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
499
}
500
501
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
502
- child->role, options, flags, child_keep_old);
503
+ child->klass, options, flags, child_keep_old);
504
}
505
506
return bs_queue;
507
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
508
} else {
509
uint64_t nperm, nshared;
510
511
- bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
512
+ bdrv_child_perm(parent->state.bs, bs, c, c->klass, q,
513
parent->state.perm, parent->state.shared_perm,
514
&nperm, &nshared);
515
516
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
517
GHashTable *found;
518
bool ret;
519
520
- if (c->role->stay_at_node) {
521
+ if (c->klass->stay_at_node) {
522
return false;
523
}
524
525
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
526
}
527
528
/* If so, update the backing file path in the image file */
529
- if (c->role->update_filename) {
530
- ret = c->role->update_filename(c, base, backing_file_str,
531
- &local_err);
532
+ if (c->klass->update_filename) {
533
+ ret = c->klass->update_filename(c, base, backing_file_str,
534
+ &local_err);
535
if (ret < 0) {
536
bdrv_abort_perm_update(base);
537
error_report_err(local_err);
538
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_parent_name(const BlockDriverState *bs)
539
540
/* If multiple parents have a name, just pick the first one. */
541
QLIST_FOREACH(c, &bs->parents, next_parent) {
542
- if (c->role->get_name) {
543
- name = c->role->get_name(c);
544
+ if (c->klass->get_name) {
545
+ name = c->klass->get_name(c);
546
if (name && *name) {
547
return name;
548
}
549
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
550
}
551
552
QLIST_FOREACH(parent, &bs->parents, next_parent) {
553
- if (parent->role->activate) {
554
- parent->role->activate(parent, &local_err);
555
+ if (parent->klass->activate) {
556
+ parent->klass->activate(parent, &local_err);
557
if (local_err) {
558
bs->open_flags |= BDRV_O_INACTIVE;
559
error_propagate(errp, local_err);
560
@@ -XXX,XX +XXX,XX @@ static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
561
BdrvChild *parent;
562
563
QLIST_FOREACH(parent, &bs->parents, next_parent) {
564
- if (parent->role->parent_is_bds) {
565
+ if (parent->klass->parent_is_bds) {
566
BlockDriverState *parent_bs = parent->opaque;
567
if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) {
568
return true;
569
@@ -XXX,XX +XXX,XX @@ static int bdrv_inactivate_recurse(BlockDriverState *bs)
570
}
571
572
QLIST_FOREACH(parent, &bs->parents, next_parent) {
573
- if (parent->role->inactivate) {
574
- ret = parent->role->inactivate(parent);
575
+ if (parent->klass->inactivate) {
576
+ ret = parent->klass->inactivate(parent);
577
if (ret < 0) {
578
return ret;
579
}
580
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
581
if (g_slist_find(*ignore, child)) {
582
continue;
583
}
584
- assert(child->role->set_aio_ctx);
585
+ assert(child->klass->set_aio_ctx);
586
*ignore = g_slist_prepend(*ignore, child);
587
- child->role->set_aio_ctx(child, new_context, ignore);
588
+ child->klass->set_aio_ctx(child, new_context, ignore);
589
}
590
591
bdrv_detach_aio_context(bs);
592
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
593
}
594
*ignore = g_slist_prepend(*ignore, c);
595
596
- /* A BdrvChildRole that doesn't handle AioContext changes cannot
597
- * tolerate any AioContext changes */
598
- if (!c->role->can_set_aio_ctx) {
599
+ /*
600
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
601
+ * tolerate any AioContext changes
602
+ */
603
+ if (!c->klass->can_set_aio_ctx) {
604
char *user = bdrv_child_user_desc(c);
605
error_setg(errp, "Changing iothreads is not supported by %s", user);
606
g_free(user);
607
return false;
608
}
609
- if (!c->role->can_set_aio_ctx(c, ctx, ignore, errp)) {
610
+ if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
611
assert(!errp || *errp);
612
return false;
613
}
614
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
615
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
616
} else {
617
QLIST_FOREACH(child, &bs->children, next) {
618
- if (child->role == &child_backing && !backing_overridden) {
619
+ if (child->klass == &child_backing && !backing_overridden) {
620
/* We can skip the backing BDS if it has not been overridden */
621
continue;
622
}
623
diff --git a/block/backup-top.c b/block/backup-top.c
624
index XXXXXXX..XXXXXXX 100644
625
--- a/block/backup-top.c
626
+++ b/block/backup-top.c
627
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
628
}
629
630
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
631
- const BdrvChildRole *role,
632
+ const BdrvChildClass *child_class,
633
BlockReopenQueue *reopen_queue,
634
uint64_t perm, uint64_t shared,
635
uint64_t *nperm, uint64_t *nshared)
636
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
35
return;
637
return;
36
}
638
}
37
639
38
- /* This BDS's file name will most probably depend on its file's name, so
640
- if (role == &child_file) {
39
- * refresh that first */
641
+ if (child_class == &child_file) {
40
- if (bs->file) {
642
/*
41
- bdrv_refresh_filename(bs->file->bs);
643
* Target child
42
+ /* This BDS's file name may depend on any of its children's file names, so
644
*
43
+ * refresh those first */
645
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
44
+ QLIST_FOREACH(child, &bs->children, next) {
646
*nperm = BLK_PERM_WRITE;
45
+ bdrv_refresh_filename(child->bs);
647
} else {
46
}
648
/* Source child */
47
649
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
48
if (drv->bdrv_refresh_filename) {
650
- nperm, nshared);
651
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
652
+ perm, shared, nperm, nshared);
653
654
if (perm & BLK_PERM_WRITE) {
655
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
656
diff --git a/block/blkdebug.c b/block/blkdebug.c
657
index XXXXXXX..XXXXXXX 100644
658
--- a/block/blkdebug.c
659
+++ b/block/blkdebug.c
660
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
661
}
662
663
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
664
- const BdrvChildRole *role,
665
+ const BdrvChildClass *child_class,
666
BlockReopenQueue *reopen_queue,
667
uint64_t perm, uint64_t shared,
668
uint64_t *nperm, uint64_t *nshared)
669
{
670
BDRVBlkdebugState *s = bs->opaque;
671
672
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
673
+ bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared,
674
nperm, nshared);
675
676
*nperm |= s->take_child_perms;
49
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
677
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
50
index XXXXXXX..XXXXXXX 100644
678
index XXXXXXX..XXXXXXX 100644
51
--- a/block/blklogwrites.c
679
--- a/block/blklogwrites.c
52
+++ b/block/blklogwrites.c
680
+++ b/block/blklogwrites.c
53
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_filename(BlockDriverState *bs,
681
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
54
{
682
}
55
BDRVBlkLogWritesState *s = bs->opaque;
683
56
684
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
57
- /* bs->file->bs has already been refreshed */
685
- const BdrvChildRole *role,
58
- bdrv_refresh_filename(s->log_file->bs);
686
+ const BdrvChildClass *child_class,
59
-
687
BlockReopenQueue *ro_q,
60
if (bs->file->bs->full_open_options
688
uint64_t perm, uint64_t shrd,
61
&& s->log_file->bs->full_open_options)
689
uint64_t *nperm, uint64_t *nshrd)
62
{
690
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
63
diff --git a/block/blkverify.c b/block/blkverify.c
691
}
64
index XXXXXXX..XXXXXXX 100644
692
65
--- a/block/blkverify.c
693
if (!strcmp(c->name, "log")) {
66
+++ b/block/blkverify.c
694
- bdrv_format_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
67
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
695
+ bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
68
{
696
+ nshrd);
69
BDRVBlkverifyState *s = bs->opaque;
697
} else {
70
698
- bdrv_filter_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
71
- /* bs->file->bs has already been refreshed */
699
+ bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
72
- bdrv_refresh_filename(s->test_file->bs);
700
+ nshrd);
73
-
701
}
74
if (bs->file->bs->full_open_options
702
}
75
&& s->test_file->bs->full_open_options)
703
76
{
704
diff --git a/block/block-backend.c b/block/block-backend.c
705
index XXXXXXX..XXXXXXX 100644
706
--- a/block/block-backend.c
707
+++ b/block/block-backend.c
708
@@ -XXX,XX +XXX,XX @@ static void blk_root_detach(BdrvChild *child)
709
}
710
}
711
712
-static const BdrvChildRole child_root = {
713
+static const BdrvChildClass child_root = {
714
.inherit_options = blk_root_inherit_options,
715
716
.change_media = blk_root_change_media,
717
@@ -XXX,XX +XXX,XX @@ static BlockBackend *bdrv_first_blk(BlockDriverState *bs)
718
{
719
BdrvChild *child;
720
QLIST_FOREACH(child, &bs->parents, next_parent) {
721
- if (child->role == &child_root) {
722
+ if (child->klass == &child_root) {
723
return child->opaque;
724
}
725
}
726
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_root_node(BlockDriverState *bs)
727
BdrvChild *c;
728
729
QLIST_FOREACH(c, &bs->parents, next_parent) {
730
- if (c->role != &child_root) {
731
+ if (c->klass != &child_root) {
732
return false;
733
}
734
}
77
diff --git a/block/commit.c b/block/commit.c
735
diff --git a/block/commit.c b/block/commit.c
78
index XXXXXXX..XXXXXXX 100644
736
index XXXXXXX..XXXXXXX 100644
79
--- a/block/commit.c
737
--- a/block/commit.c
80
+++ b/block/commit.c
738
+++ b/block/commit.c
81
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
739
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
82
740
}
83
static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
741
84
{
742
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
85
- bdrv_refresh_filename(bs->backing->bs);
743
- const BdrvChildRole *role,
86
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
744
+ const BdrvChildClass *child_class,
87
bs->backing->bs->filename);
745
BlockReopenQueue *reopen_queue,
746
uint64_t perm, uint64_t shared,
747
uint64_t *nperm, uint64_t *nshared)
748
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
749
index XXXXXXX..XXXXXXX 100644
750
--- a/block/copy-on-read.c
751
+++ b/block/copy-on-read.c
752
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
753
#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
754
755
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
756
- const BdrvChildRole *role,
757
+ const BdrvChildClass *child_class,
758
BlockReopenQueue *reopen_queue,
759
uint64_t perm, uint64_t shared,
760
uint64_t *nperm, uint64_t *nshared)
761
diff --git a/block/io.c b/block/io.c
762
index XXXXXXX..XXXXXXX 100644
763
--- a/block/io.c
764
+++ b/block/io.c
765
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore,
766
BdrvChild *c, *next;
767
768
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
769
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
770
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
771
continue;
772
}
773
bdrv_parent_drained_begin_single(c, false);
774
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end_single_no_poll(BdrvChild *c,
775
{
776
assert(c->parent_quiesce_counter > 0);
777
c->parent_quiesce_counter--;
778
- if (c->role->drained_end) {
779
- c->role->drained_end(c, drained_end_counter);
780
+ if (c->klass->drained_end) {
781
+ c->klass->drained_end(c, drained_end_counter);
782
}
783
}
784
785
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
786
BdrvChild *c;
787
788
QLIST_FOREACH(c, &bs->parents, next_parent) {
789
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
790
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
791
continue;
792
}
793
bdrv_parent_drained_end_single_no_poll(c, drained_end_counter);
794
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore,
795
796
static bool bdrv_parent_drained_poll_single(BdrvChild *c)
797
{
798
- if (c->role->drained_poll) {
799
- return c->role->drained_poll(c);
800
+ if (c->klass->drained_poll) {
801
+ return c->klass->drained_poll(c);
802
}
803
return false;
804
}
805
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
806
bool busy = false;
807
808
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
809
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
810
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
811
continue;
812
}
813
busy |= bdrv_parent_drained_poll_single(c);
814
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_drained_poll(BlockDriverState *bs, BdrvChild *ignore,
815
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
816
{
817
c->parent_quiesce_counter++;
818
- if (c->role->drained_begin) {
819
- c->role->drained_begin(c);
820
+ if (c->klass->drained_begin) {
821
+ c->klass->drained_begin(c);
822
}
823
if (poll) {
824
BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c));
825
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
826
{
827
BdrvChild *c;
828
QLIST_FOREACH(c, &bs->parents, next_parent) {
829
- if (c->role->resize) {
830
- c->role->resize(c);
831
+ if (c->klass->resize) {
832
+ c->klass->resize(c);
833
}
834
}
88
}
835
}
89
diff --git a/block/mirror.c b/block/mirror.c
836
diff --git a/block/mirror.c b/block/mirror.c
90
index XXXXXXX..XXXXXXX 100644
837
index XXXXXXX..XXXXXXX 100644
91
--- a/block/mirror.c
838
--- a/block/mirror.c
92
+++ b/block/mirror.c
839
+++ b/block/mirror.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
840
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
94
* bdrv_set_backing_hd */
841
}
95
return;
842
96
}
843
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
97
- bdrv_refresh_filename(bs->backing->bs);
844
- const BdrvChildRole *role,
98
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
845
+ const BdrvChildClass *child_class,
99
bs->backing->bs->filename);
846
BlockReopenQueue *reopen_queue,
100
}
847
uint64_t perm, uint64_t shared,
848
uint64_t *nperm, uint64_t *nshared)
101
diff --git a/block/quorum.c b/block/quorum.c
849
diff --git a/block/quorum.c b/block/quorum.c
102
index XXXXXXX..XXXXXXX 100644
850
index XXXXXXX..XXXXXXX 100644
103
--- a/block/quorum.c
851
--- a/block/quorum.c
104
+++ b/block/quorum.c
852
+++ b/block/quorum.c
105
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
853
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
854
}
855
856
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
857
- const BdrvChildRole *role,
858
+ const BdrvChildClass *child_class,
859
BlockReopenQueue *reopen_queue,
860
uint64_t perm, uint64_t shared,
861
uint64_t *nperm, uint64_t *nshared)
862
diff --git a/block/replication.c b/block/replication.c
863
index XXXXXXX..XXXXXXX 100644
864
--- a/block/replication.c
865
+++ b/block/replication.c
866
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
867
}
868
869
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
870
- const BdrvChildRole *role,
871
+ const BdrvChildClass *child_class,
872
BlockReopenQueue *reopen_queue,
873
uint64_t perm, uint64_t shared,
874
uint64_t *nperm, uint64_t *nshared)
875
diff --git a/block/vvfat.c b/block/vvfat.c
876
index XXXXXXX..XXXXXXX 100644
877
--- a/block/vvfat.c
878
+++ b/block/vvfat.c
879
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
880
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
881
}
882
883
-static const BdrvChildRole child_vvfat_qcow = {
884
+static const BdrvChildClass child_vvfat_qcow = {
885
.parent_is_bds = true,
886
.inherit_options = vvfat_qcow_options,
887
};
888
@@ -XXX,XX +XXX,XX @@ err:
889
}
890
891
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
892
- const BdrvChildRole *role,
893
+ const BdrvChildClass *child_class,
894
BlockReopenQueue *reopen_queue,
895
uint64_t perm, uint64_t shared,
896
uint64_t *nperm, uint64_t *nshared)
897
{
898
BDRVVVFATState *s = bs->opaque;
899
900
- assert(c == s->qcow || role == &child_backing);
901
+ assert(c == s->qcow || child_class == &child_backing);
902
903
if (c == s->qcow) {
904
/* This is a private node, nobody should try to attach to it */
905
diff --git a/blockjob.c b/blockjob.c
906
index XXXXXXX..XXXXXXX 100644
907
--- a/blockjob.c
908
+++ b/blockjob.c
909
@@ -XXX,XX +XXX,XX @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
910
job->job.aio_context = ctx;
911
}
912
913
-static const BdrvChildRole child_job = {
914
+static const BdrvChildClass child_job = {
915
.get_parent_desc = child_job_get_parent_desc,
916
.drained_begin = child_job_drained_begin,
917
.drained_poll = child_job_drained_poll,
918
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
919
index XXXXXXX..XXXXXXX 100644
920
--- a/tests/test-bdrv-drain.c
921
+++ b/tests/test-bdrv-drain.c
922
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
923
}
924
925
static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
926
- const BdrvChildRole *role,
927
+ const BdrvChildClass *child_class,
928
BlockReopenQueue *reopen_queue,
929
uint64_t perm, uint64_t shared,
930
uint64_t *nperm, uint64_t *nshared)
931
{
932
- /* bdrv_format_default_perms() accepts only these two, so disguise
933
- * detach_by_driver_cb_role as one of them. */
934
- if (role != &child_file && role != &child_backing) {
935
- role = &child_file;
936
+ /*
937
+ * bdrv_format_default_perms() accepts only these two, so disguise
938
+ * detach_by_driver_cb_parent as one of them.
939
+ */
940
+ if (child_class != &child_file && child_class != &child_backing) {
941
+ child_class = &child_file;
942
}
943
944
- bdrv_format_default_perms(bs, c, role, reopen_queue, perm, shared,
945
+ bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared,
946
nperm, nshared);
947
}
948
949
@@ -XXX,XX +XXX,XX @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child)
950
child_file.drained_begin(child);
951
}
952
953
-static BdrvChildRole detach_by_driver_cb_role;
954
+static BdrvChildClass detach_by_driver_cb_class;
955
956
/*
957
* Initial graph:
958
@@ -XXX,XX +XXX,XX @@ static BdrvChildRole detach_by_driver_cb_role;
959
*
960
* by_parent_cb == false: Test that bdrv_drain_invoke() doesn't poll
961
*
962
- * PA's BdrvChildRole has a .drained_begin callback that schedules a BH
963
+ * PA's BdrvChildClass has a .drained_begin callback that schedules a BH
964
* that does the same graph change. If bdrv_drain_invoke() calls it, the
965
* state is messed up, but if it is only polled in the single
966
* BDRV_POLL_WHILE() at the end of the drain, this should work fine.
967
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
968
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
969
970
if (!by_parent_cb) {
971
- detach_by_driver_cb_role = child_file;
972
- detach_by_driver_cb_role.drained_begin =
973
+ detach_by_driver_cb_class = child_file;
974
+ detach_by_driver_cb_class.drained_begin =
975
detach_by_driver_cb_drained_begin;
976
}
977
978
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
979
980
bdrv_ref(a);
981
bdrv_attach_child(parent_a, a, "PA-A",
982
- by_parent_cb ? &child_file : &detach_by_driver_cb_role,
983
+ by_parent_cb ? &child_file : &detach_by_driver_cb_class,
984
&error_abort);
985
986
g_assert_cmpint(parent_a->refcnt, ==, 1);
987
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
988
/**
989
* Test a poll in the midst of bdrv_drop_intermediate().
990
*
991
- * bdrv_drop_intermediate() calls BdrvChildRole.update_filename(),
992
+ * bdrv_drop_intermediate() calls BdrvChildClass.update_filename(),
993
* which can yield or poll. This may lead to graph changes, unless
994
* the whole subtree in question is drained.
995
*
996
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
997
*
998
* The solution is for bdrv_drop_intermediate() to drain top's
999
* subtree. This prevents graph changes from happening just because
1000
- * BdrvChildRole.update_filename() yields or polls. Thus, the block
1001
+ * BdrvChildClass.update_filename() yields or polls. Thus, the block
1002
* job is paused during that drained section and must finish before or
1003
* after.
1004
*
1005
@@ -XXX,XX +XXX,XX @@ static int drop_intermediate_poll_update_filename(BdrvChild *child,
1006
*/
1007
static void test_drop_intermediate_poll(void)
1008
{
1009
- static BdrvChildRole chain_child_role;
1010
+ static BdrvChildClass chain_child_class;
1011
BlockDriverState *chain[3];
1012
TestSimpleBlockJob *job;
1013
BlockDriverState *job_node;
1014
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
106
int i;
1015
int i;
107
1016
int ret;
108
for (i = 0; i < s->num_children; i++) {
1017
109
- bdrv_refresh_filename(s->children[i]->bs);
1018
- chain_child_role = child_backing;
110
if (!s->children[i]->bs->full_open_options) {
1019
- chain_child_role.update_filename = drop_intermediate_poll_update_filename;
111
return;
1020
+ chain_child_class = child_backing;
112
}
1021
+ chain_child_class.update_filename = drop_intermediate_poll_update_filename;
1022
1023
for (i = 0; i < 3; i++) {
1024
char name[32];
1025
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
1026
if (i) {
1027
/* Takes the reference to chain[i - 1] */
1028
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
1029
- "chain", &chain_child_role,
1030
+ "chain", &chain_child_class,
1031
&error_abort);
1032
}
1033
}
1034
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
1035
index XXXXXXX..XXXXXXX 100644
1036
--- a/tests/test-bdrv-graph-mod.c
1037
+++ b/tests/test-bdrv-graph-mod.c
1038
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
1039
};
1040
1041
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
1042
- const BdrvChildRole *role,
1043
+ const BdrvChildClass *child_class,
1044
BlockReopenQueue *reopen_queue,
1045
uint64_t perm, uint64_t shared,
1046
uint64_t *nperm, uint64_t *nshared)
113
--
1047
--
114
2.20.1
1048
2.25.4
115
1049
116
1050
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Make bdrv_get_full_backing_filename_from_filename() return an allocated
3
This mask will supplement BdrvChildClass when it comes to what role (or
4
string instead of placing the result in a caller-provided buffer.
4
combination of roles) a child takes for its parent. It consists of
5
BdrvChildRoleBits values (which is an enum).
6
7
Because empty enums are not allowed, let us just start with it filled.
5
8
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190201192935.18394-11-mreitz@redhat.com
10
Message-Id: <20200513110544.176672-5-mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
include/block/block.h | 7 +++---
14
include/block/block.h | 56 +++++++++++++++++++++++++++++++++++++++++++
11
block.c | 53 ++++++++++++++++++++++++++++++-------------
15
1 file changed, 56 insertions(+)
12
block/vmdk.c | 10 ++++----
13
qemu-img.c | 12 ++++------
14
4 files changed, 49 insertions(+), 33 deletions(-)
15
16
16
diff --git a/include/block/block.h b/include/block/block.h
17
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
19
--- a/include/block/block.h
19
+++ b/include/block/block.h
20
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ enum {
21
char *filename, int filename_size);
22
DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
22
void bdrv_get_full_backing_filename(BlockDriverState *bs,
23
};
23
char *dest, size_t sz, Error **errp);
24
24
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
25
- const char *backing,
26
- char *dest, size_t sz,
27
- Error **errp);
28
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
29
+ const char *backing,
30
+ Error **errp);
31
32
int path_has_protocol(const char *path);
33
int path_is_absolute(const char *path);
34
diff --git a/block.c b/block.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block.c
37
+++ b/block.c
38
@@ -XXX,XX +XXX,XX @@ fail:
39
return -EACCES;
40
}
41
42
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
43
- const char *backing,
44
- char *dest, size_t sz,
45
- Error **errp)
46
+/*
25
+/*
47
+ * If @backing is empty, this function returns NULL without setting
26
+ * Flags that parent nodes assign to child nodes to specify what kind of
48
+ * @errp. In all other cases, NULL will only be returned with @errp
27
+ * role(s) they take.
49
+ * set.
50
+ *
28
+ *
51
+ * Therefore, a return value of NULL without @errp set means that
29
+ * At least one of DATA, METADATA, FILTERED, or COW must be set for
52
+ * there is no backing file; if @errp is set, there is one but its
30
+ * every child.
53
+ * absolute filename cannot be generated.
54
+ */
31
+ */
55
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
32
+enum BdrvChildRoleBits {
56
+ const char *backing,
33
+ /*
57
+ Error **errp)
34
+ * This child stores data.
58
{
35
+ * Any node may have an arbitrary number of such children.
59
- if (backing[0] == '\0' || path_has_protocol(backing) ||
36
+ */
60
- path_is_absolute(backing))
37
+ BDRV_CHILD_DATA = (1 << 0),
61
- {
62
- pstrcpy(dest, sz, backing);
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
}
75
}
76
77
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
78
Error **errp)
79
{
80
char *backed;
81
+ char *full_name;
82
+ Error *local_error = NULL;
83
84
bdrv_refresh_filename(bs);
85
86
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
87
- bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
88
- dest, sz, errp);
89
+
38
+
90
+ full_name = bdrv_get_full_backing_filename_from_filename(backed,
39
+ /*
91
+ bs->backing_file,
40
+ * This child stores metadata.
92
+ &local_error);
41
+ * Any node may have an arbitrary number of metadata-storing
93
+ if (full_name) {
42
+ * children.
94
+ pstrcpy(dest, sz, full_name);
43
+ */
95
+ g_free(full_name);
44
+ BDRV_CHILD_METADATA = (1 << 1),
96
+ } else if (local_error) {
45
+
97
+ error_propagate(errp, local_error);
46
+ /*
98
+ } else if (sz > 0) {
47
+ * A child that always presents exactly the same visible data as
99
+ *dest = '\0';
48
+ * the parent, e.g. by virtue of the parent forwarding all reads
100
+ }
49
+ * and writes.
101
}
50
+ * This flag is mutually exclusive with DATA, METADATA, and COW.
102
51
+ * Any node may have at most one filtered child at a time.
103
void bdrv_register(BlockDriver *bdrv)
52
+ */
104
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
53
+ BDRV_CHILD_FILTERED = (1 << 2),
105
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
54
+
106
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
55
+ /*
107
BlockDriverState *bs;
56
+ * Child from which to read all data that isn’t allocated in the
108
- char *full_backing = g_new0(char, PATH_MAX);
57
+ * parent (i.e., the backing child); such data is copied to the
109
+ char *full_backing;
58
+ * parent through COW (and optionally COR).
110
int back_flags;
59
+ * This field is mutually exclusive with DATA, METADATA, and
111
QDict *backing_options = NULL;
60
+ * FILTERED.
112
61
+ * Any node may have at most one such backing child at a time.
113
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
62
+ */
114
- full_backing, PATH_MAX,
63
+ BDRV_CHILD_COW = (1 << 3),
115
- &local_err);
64
+
116
+ full_backing =
65
+ /*
117
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
66
+ * The primary child. For most drivers, this is the child whose
118
+ &local_err);
67
+ * filename applies best to the parent node.
119
if (local_err) {
68
+ * Any node may have at most one primary child at a time.
120
- g_free(full_backing);
69
+ */
121
goto out;
70
+ BDRV_CHILD_PRIMARY = (1 << 4),
122
}
71
+
123
+ assert(full_backing);
72
+ /* Useful combination of flags */
124
73
+ BDRV_CHILD_IMAGE = BDRV_CHILD_DATA
125
/* backing files always opened read-only */
74
+ | BDRV_CHILD_METADATA
126
back_flags = flags;
75
+ | BDRV_CHILD_PRIMARY,
127
diff --git a/block/vmdk.c b/block/vmdk.c
76
+};
128
index XXXXXXX..XXXXXXX 100644
77
+
129
--- a/block/vmdk.c
78
+/* Mask of BdrvChildRoleBits values */
130
+++ b/block/vmdk.c
79
+typedef unsigned int BdrvChildRole;
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
80
+
132
81
char *bdrv_perm_names(uint64_t perm);
133
if (backing_file) {
82
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
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
83
180
--
84
--
181
2.20.1
85
2.25.4
182
86
183
87
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This new field can be set by block drivers to list the runtime options
3
For now, it is always set to 0. Later patches in this series will
4
they accept that may influence the contents of the respective BDS. As of
4
ensure that all callers pass an appropriate combination of flags.
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
11
Additionally, this patch adds the field to all of the block drivers that
12
need it and sets it accordingly.
13
5
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Message-id: 20190201192935.18394-22-mreitz@redhat.com
8
Message-Id: <20200513110544.176672-6-mreitz@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
10
---
19
include/block/block_int.h | 7 +++++++
11
include/block/block.h | 2 ++
20
block/blkdebug.c | 16 ++++++++++++++++
12
include/block/block_int.h | 2 ++
21
block/blklogwrites.c | 8 ++++++++
13
block.c | 11 ++++++++---
22
block/crypto.c | 8 ++++++++
14
block/backup-top.c | 3 ++-
23
block/curl.c | 21 +++++++++++++++++++++
15
block/blkdebug.c | 2 +-
24
block/gluster.c | 19 +++++++++++++++++++
16
block/blklogwrites.c | 6 +++---
25
block/iscsi.c | 18 ++++++++++++++++++
17
block/blkreplay.c | 2 +-
26
block/nbd.c | 14 ++++++++++++++
18
block/blkverify.c | 4 ++--
27
block/nfs.c | 11 +++++++++++
19
block/block-backend.c | 4 ++--
28
block/null.c | 9 +++++++++
20
block/bochs.c | 2 +-
29
block/nvme.c | 8 ++++++++
21
block/cloop.c | 2 +-
30
block/qcow.c | 7 +++++++
22
block/copy-on-read.c | 2 +-
31
block/qcow2.c | 7 +++++++
23
block/crypto.c | 2 +-
32
block/quorum.c | 11 +++++++++++
24
block/dmg.c | 2 +-
33
block/raw-format.c | 10 +++++++++-
25
block/filter-compress.c | 2 +-
34
block/rbd.c | 14 ++++++++++++++
26
block/parallels.c | 2 +-
35
block/replication.c | 8 ++++++++
27
block/qcow.c | 2 +-
36
block/sheepdog.c | 12 ++++++++++++
28
block/qcow2.c | 6 +++---
37
block/ssh.c | 12 ++++++++++++
29
block/qed.c | 2 +-
38
block/throttle.c | 7 +++++++
30
block/quorum.c | 4 ++--
39
block/vpc.c | 7 +++++++
31
block/raw-format.c | 2 +-
40
block/vvfat.c | 12 ++++++++++++
32
block/replication.c | 2 +-
41
block/vxhs.c | 11 +++++++++++
33
block/throttle.c | 2 +-
42
23 files changed, 256 insertions(+), 1 deletion(-)
34
block/vdi.c | 2 +-
35
block/vhdx.c | 2 +-
36
block/vmdk.c | 4 ++--
37
block/vpc.c | 2 +-
38
block/vvfat.c | 2 +-
39
blockjob.c | 5 +++--
40
tests/test-bdrv-drain.c | 20 +++++++++++---------
41
tests/test-bdrv-graph-mod.c | 4 ++--
42
31 files changed, 62 insertions(+), 49 deletions(-)
43
43
44
diff --git a/include/block/block.h b/include/block/block.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block.h
47
+++ b/include/block/block.h
48
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
49
QDict *options, const char *bdref_key,
50
BlockDriverState* parent,
51
const BdrvChildClass *child_class,
52
+ BdrvChildRole child_role,
53
bool allow_none, Error **errp);
54
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
55
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
56
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
57
BlockDriverState *child_bs,
58
const char *child_name,
59
const BdrvChildClass *child_class,
60
+ BdrvChildRole child_role,
61
Error **errp);
62
63
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
64
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
66
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
67
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
68
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
49
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
69
BlockDriverState *bs;
50
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
70
char *name;
51
QLIST_ENTRY(BlockDriver) list;
71
const BdrvChildClass *klass;
52
+
72
+ BdrvChildRole role;
53
+ /* Pointer to a NULL-terminated array of names of strong options
73
void *opaque;
54
+ * that can be specified for bdrv_open(). A strong option is one
74
55
+ * that changes the data of a BDS.
75
/**
56
+ * If this pointer is NULL, the array is considered empty.
76
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
57
+ * "filename" and "driver" are always considered strong. */
77
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
58
+ const char *const *strong_runtime_opts;
78
const char *child_name,
59
};
79
const BdrvChildClass *child_class,
60
80
+ BdrvChildRole child_role,
61
typedef struct BlockLimits {
81
AioContext *ctx,
82
uint64_t perm, uint64_t shared_perm,
83
void *opaque, Error **errp);
84
diff --git a/block.c b/block.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block.c
87
+++ b/block.c
88
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
89
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
90
const char *child_name,
91
const BdrvChildClass *child_class,
92
+ BdrvChildRole child_role,
93
AioContext *ctx,
94
uint64_t perm, uint64_t shared_perm,
95
void *opaque, Error **errp)
96
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
97
.bs = NULL,
98
.name = g_strdup(child_name),
99
.klass = child_class,
100
+ .role = child_role,
101
.perm = perm,
102
.shared_perm = shared_perm,
103
.opaque = opaque,
104
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
105
BlockDriverState *child_bs,
106
const char *child_name,
107
const BdrvChildClass *child_class,
108
+ BdrvChildRole child_role,
109
Error **errp)
110
{
111
BdrvChild *child;
112
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
113
perm, shared_perm, &perm, &shared_perm);
114
115
child = bdrv_root_attach_child(child_bs, child_name, child_class,
116
- bdrv_get_aio_context(parent_bs),
117
+ child_role, bdrv_get_aio_context(parent_bs),
118
perm, shared_perm, parent_bs, errp);
119
if (child == NULL) {
120
return NULL;
121
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
122
}
123
124
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
125
- errp);
126
+ 0, errp);
127
/* If backing_hd was already part of bs's backing chain, and
128
* inherits_from pointed recursively to bs then let's update it to
129
* point directly to bs (else it will become NULL). */
130
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
131
QDict *options, const char *bdref_key,
132
BlockDriverState *parent,
133
const BdrvChildClass *child_class,
134
+ BdrvChildRole child_role,
135
bool allow_none, Error **errp)
136
{
137
BlockDriverState *bs;
138
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
139
return NULL;
140
}
141
142
- return bdrv_attach_child(parent, bs, bdref_key, child_class, errp);
143
+ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
144
+ errp);
145
}
146
147
/*
148
diff --git a/block/backup-top.c b/block/backup-top.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/backup-top.c
151
+++ b/block/backup-top.c
152
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
153
source->supported_zero_flags);
154
155
bdrv_ref(target);
156
- state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
157
+ state->target = bdrv_attach_child(top, target, "target", &child_file, 0,
158
+ errp);
159
if (!state->target) {
160
bdrv_unref(target);
161
bdrv_unref(top);
62
diff --git a/block/blkdebug.c b/block/blkdebug.c
162
diff --git a/block/blkdebug.c b/block/blkdebug.c
63
index XXXXXXX..XXXXXXX 100644
163
index XXXXXXX..XXXXXXX 100644
64
--- a/block/blkdebug.c
164
--- a/block/blkdebug.c
65
+++ b/block/blkdebug.c
165
+++ b/block/blkdebug.c
66
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
166
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
67
return 0;
167
68
}
168
/* Open the image file */
69
169
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
70
+static const char *const blkdebug_strong_runtime_opts[] = {
170
- bs, &child_file, false, &local_err);
71
+ "config",
171
+ bs, &child_file, 0, false, &local_err);
72
+ "inject-error.",
172
if (local_err) {
73
+ "set-state.",
173
ret = -EINVAL;
74
+ "align",
174
error_propagate(errp, local_err);
75
+ "max-transfer",
76
+ "opt-write-zero",
77
+ "max-write-zero",
78
+ "opt-discard",
79
+ "max-discard",
80
+
81
+ NULL
82
+};
83
+
84
static BlockDriver bdrv_blkdebug = {
85
.format_name = "blkdebug",
86
.protocol_name = "blkdebug",
87
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
88
= blkdebug_debug_remove_breakpoint,
89
.bdrv_debug_resume = blkdebug_debug_resume,
90
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
91
+
92
+ .strong_runtime_opts = blkdebug_strong_runtime_opts,
93
};
94
95
static void bdrv_blkdebug_init(void)
96
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
175
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
97
index XXXXXXX..XXXXXXX 100644
176
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blklogwrites.c
177
--- a/block/blklogwrites.c
99
+++ b/block/blklogwrites.c
178
+++ b/block/blklogwrites.c
100
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
179
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
101
LOG_DISCARD_FLAG, false);
180
}
102
}
181
103
182
/* Open the file */
104
+static const char *const blk_log_writes_strong_runtime_opts[] = {
183
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
105
+ "log-append",
184
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
106
+ "log-sector-size",
185
&local_err);
107
+
186
if (local_err) {
108
+ NULL
187
ret = -EINVAL;
109
+};
188
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
110
+
189
}
111
static BlockDriver bdrv_blk_log_writes = {
190
112
.format_name = "blklogwrites",
191
/* Open the log file */
113
.instance_size = sizeof(BDRVBlkLogWritesState),
192
- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, false,
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
193
- &local_err);
115
.bdrv_co_block_status = bdrv_co_block_status_from_file,
194
+ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0,
116
195
+ false, &local_err);
117
.is_filter = true,
196
if (local_err) {
118
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
197
ret = -EINVAL;
119
};
198
error_propagate(errp, local_err);
120
199
diff --git a/block/blkreplay.c b/block/blkreplay.c
121
static void bdrv_blk_log_writes_init(void)
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/blkreplay.c
202
+++ b/block/blkreplay.c
203
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
204
205
/* Open the image file */
206
bs->file = bdrv_open_child(NULL, options, "image",
207
- bs, &child_file, false, &local_err);
208
+ bs, &child_file, 0, false, &local_err);
209
if (local_err) {
210
ret = -EINVAL;
211
error_propagate(errp, local_err);
212
diff --git a/block/blkverify.c b/block/blkverify.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/blkverify.c
215
+++ b/block/blkverify.c
216
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
217
218
/* Open the raw file */
219
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
220
- bs, &child_file, false, &local_err);
221
+ bs, &child_file, 0, false, &local_err);
222
if (local_err) {
223
ret = -EINVAL;
224
error_propagate(errp, local_err);
225
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
226
227
/* Open the test file */
228
s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
229
- "test", bs, &child_format, false,
230
+ "test", bs, &child_format, 0, false,
231
&local_err);
232
if (local_err) {
233
ret = -EINVAL;
234
diff --git a/block/block-backend.c b/block/block-backend.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/block/block-backend.c
237
+++ b/block/block-backend.c
238
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
239
return NULL;
240
}
241
242
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
243
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
244
perm, BLK_PERM_ALL, blk, errp);
245
if (!blk->root) {
246
blk_unref(blk);
247
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
248
{
249
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
250
bdrv_ref(bs);
251
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
252
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
253
blk->perm, blk->shared_perm, blk, errp);
254
if (blk->root == NULL) {
255
return -EPERM;
256
diff --git a/block/bochs.c b/block/bochs.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/bochs.c
259
+++ b/block/bochs.c
260
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
261
return ret;
262
}
263
264
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
265
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
266
false, errp);
267
if (!bs->file) {
268
return -EINVAL;
269
diff --git a/block/cloop.c b/block/cloop.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/cloop.c
272
+++ b/block/cloop.c
273
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
274
return ret;
275
}
276
277
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
278
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
279
false, errp);
280
if (!bs->file) {
281
return -EINVAL;
282
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/copy-on-read.c
285
+++ b/block/copy-on-read.c
286
@@ -XXX,XX +XXX,XX @@
287
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
288
Error **errp)
289
{
290
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
291
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
292
errp);
293
if (!bs->file) {
294
return -EINVAL;
122
diff --git a/block/crypto.c b/block/crypto.c
295
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
296
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
297
--- a/block/crypto.c
125
+++ b/block/crypto.c
298
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
299
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
127
return spec_info;
300
unsigned int cflags = 0;
128
}
301
QDict *cryptoopts = NULL;
129
302
130
+static const char *const block_crypto_strong_runtime_opts[] = {
303
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
131
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
304
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
132
+
305
false, errp);
133
+ NULL
306
if (!bs->file) {
134
+};
307
return -EINVAL;
135
+
308
diff --git a/block/dmg.c b/block/dmg.c
136
BlockDriver bdrv_crypto_luks = {
309
index XXXXXXX..XXXXXXX 100644
137
.format_name = "luks",
310
--- a/block/dmg.c
138
.instance_size = sizeof(BlockCrypto),
311
+++ b/block/dmg.c
139
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
312
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
140
.bdrv_getlength = block_crypto_getlength,
313
return ret;
141
.bdrv_get_info = block_crypto_get_info_luks,
314
}
142
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
315
143
+
316
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
144
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
317
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
145
};
318
false, errp);
146
319
if (!bs->file) {
147
static void block_crypto_init(void)
320
return -EINVAL;
148
diff --git a/block/curl.c b/block/curl.c
321
diff --git a/block/filter-compress.c b/block/filter-compress.c
149
index XXXXXXX..XXXXXXX 100644
322
index XXXXXXX..XXXXXXX 100644
150
--- a/block/curl.c
323
--- a/block/filter-compress.c
151
+++ b/block/curl.c
324
+++ b/block/filter-compress.c
152
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
325
@@ -XXX,XX +XXX,XX @@
153
return s->len;
326
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
154
}
327
Error **errp)
155
328
{
156
+static const char *const curl_strong_runtime_opts[] = {
329
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
157
+ CURL_BLOCK_OPT_URL,
330
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
158
+ CURL_BLOCK_OPT_SSLVERIFY,
331
errp);
159
+ CURL_BLOCK_OPT_COOKIE,
332
if (!bs->file) {
160
+ CURL_BLOCK_OPT_COOKIE_SECRET,
333
return -EINVAL;
161
+ CURL_BLOCK_OPT_USERNAME,
334
diff --git a/block/parallels.c b/block/parallels.c
162
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
335
index XXXXXXX..XXXXXXX 100644
163
+ CURL_BLOCK_OPT_PROXY_USERNAME,
336
--- a/block/parallels.c
164
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
337
+++ b/block/parallels.c
165
+
338
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
166
+ NULL
339
Error *local_err = NULL;
167
+};
340
char *buf;
168
+
341
169
static BlockDriver bdrv_http = {
342
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
170
.format_name = "http",
343
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
171
.protocol_name = "http",
344
false, errp);
172
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
345
if (!bs->file) {
173
346
return -EINVAL;
174
.bdrv_detach_aio_context = curl_detach_aio_context,
175
.bdrv_attach_aio_context = curl_attach_aio_context,
176
+
177
+ .strong_runtime_opts = curl_strong_runtime_opts,
178
};
179
180
static BlockDriver bdrv_https = {
181
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
182
183
.bdrv_detach_aio_context = curl_detach_aio_context,
184
.bdrv_attach_aio_context = curl_attach_aio_context,
185
+
186
+ .strong_runtime_opts = curl_strong_runtime_opts,
187
};
188
189
static BlockDriver bdrv_ftp = {
190
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
191
192
.bdrv_detach_aio_context = curl_detach_aio_context,
193
.bdrv_attach_aio_context = curl_attach_aio_context,
194
+
195
+ .strong_runtime_opts = curl_strong_runtime_opts,
196
};
197
198
static BlockDriver bdrv_ftps = {
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
200
201
.bdrv_detach_aio_context = curl_detach_aio_context,
202
.bdrv_attach_aio_context = curl_attach_aio_context,
203
+
204
+ .strong_runtime_opts = curl_strong_runtime_opts,
205
};
206
207
static void curl_block_init(void)
208
diff --git a/block/gluster.c b/block/gluster.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/gluster.c
211
+++ b/block/gluster.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
213
}
214
215
216
+static const char *const gluster_strong_open_opts[] = {
217
+ GLUSTER_OPT_VOLUME,
218
+ GLUSTER_OPT_PATH,
219
+ GLUSTER_OPT_TYPE,
220
+ GLUSTER_OPT_SERVER_PATTERN,
221
+ GLUSTER_OPT_HOST,
222
+ GLUSTER_OPT_PORT,
223
+ GLUSTER_OPT_TO,
224
+ GLUSTER_OPT_IPV4,
225
+ GLUSTER_OPT_IPV6,
226
+ GLUSTER_OPT_SOCKET,
227
+
228
+ NULL
229
+};
230
+
231
static BlockDriver bdrv_gluster = {
232
.format_name = "gluster",
233
.protocol_name = "gluster",
234
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
235
#endif
236
.bdrv_co_block_status = qemu_gluster_co_block_status,
237
.create_opts = &qemu_gluster_create_opts,
238
+ .strong_runtime_opts = gluster_strong_open_opts,
239
};
240
241
static BlockDriver bdrv_gluster_tcp = {
242
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
243
#endif
244
.bdrv_co_block_status = qemu_gluster_co_block_status,
245
.create_opts = &qemu_gluster_create_opts,
246
+ .strong_runtime_opts = gluster_strong_open_opts,
247
};
248
249
static BlockDriver bdrv_gluster_unix = {
250
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
251
#endif
252
.bdrv_co_block_status = qemu_gluster_co_block_status,
253
.create_opts = &qemu_gluster_create_opts,
254
+ .strong_runtime_opts = gluster_strong_open_opts,
255
};
256
257
/* rdma is deprecated (actually never supported for volfile fetch).
258
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
259
#endif
260
.bdrv_co_block_status = qemu_gluster_co_block_status,
261
.create_opts = &qemu_gluster_create_opts,
262
+ .strong_runtime_opts = gluster_strong_open_opts,
263
};
264
265
static void bdrv_gluster_init(void)
266
diff --git a/block/iscsi.c b/block/iscsi.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/block/iscsi.c
269
+++ b/block/iscsi.c
270
@@ -XXX,XX +XXX,XX @@ static QemuOptsList iscsi_create_opts = {
271
}
272
};
273
274
+static const char *const iscsi_strong_runtime_opts[] = {
275
+ "transport",
276
+ "portal",
277
+ "target",
278
+ "user",
279
+ "password",
280
+ "password-secret",
281
+ "lun",
282
+ "initiator-name",
283
+ "header-digest",
284
+
285
+ NULL
286
+};
287
+
288
static BlockDriver bdrv_iscsi = {
289
.format_name = "iscsi",
290
.protocol_name = "iscsi",
291
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
292
293
.bdrv_detach_aio_context = iscsi_detach_aio_context,
294
.bdrv_attach_aio_context = iscsi_attach_aio_context,
295
+
296
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
297
};
298
299
#if LIBISCSI_API_VERSION >= (20160603)
300
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
301
302
.bdrv_detach_aio_context = iscsi_detach_aio_context,
303
.bdrv_attach_aio_context = iscsi_attach_aio_context,
304
+
305
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
306
};
307
#endif
308
309
diff --git a/block/nbd.c b/block/nbd.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/block/nbd.c
312
+++ b/block/nbd.c
313
@@ -XXX,XX +XXX,XX @@ static char *nbd_dirname(BlockDriverState *bs, Error **errp)
314
return NULL;
315
}
316
317
+static const char *const nbd_strong_runtime_opts[] = {
318
+ "path",
319
+ "host",
320
+ "port",
321
+ "export",
322
+ "tls-creds",
323
+ "server.",
324
+
325
+ NULL
326
+};
327
+
328
static BlockDriver bdrv_nbd = {
329
.format_name = "nbd",
330
.protocol_name = "nbd",
331
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
332
.bdrv_refresh_filename = nbd_refresh_filename,
333
.bdrv_co_block_status = nbd_client_co_block_status,
334
.bdrv_dirname = nbd_dirname,
335
+ .strong_runtime_opts = nbd_strong_runtime_opts,
336
};
337
338
static BlockDriver bdrv_nbd_tcp = {
339
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
340
.bdrv_refresh_filename = nbd_refresh_filename,
341
.bdrv_co_block_status = nbd_client_co_block_status,
342
.bdrv_dirname = nbd_dirname,
343
+ .strong_runtime_opts = nbd_strong_runtime_opts,
344
};
345
346
static BlockDriver bdrv_nbd_unix = {
347
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
348
.bdrv_refresh_filename = nbd_refresh_filename,
349
.bdrv_co_block_status = nbd_client_co_block_status,
350
.bdrv_dirname = nbd_dirname,
351
+ .strong_runtime_opts = nbd_strong_runtime_opts,
352
};
353
354
static void bdrv_nbd_init(void)
355
diff --git a/block/nfs.c b/block/nfs.c
356
index XXXXXXX..XXXXXXX 100644
357
--- a/block/nfs.c
358
+++ b/block/nfs.c
359
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
360
}
361
#endif
362
363
+static const char *nfs_strong_runtime_opts[] = {
364
+ "path",
365
+ "user",
366
+ "group",
367
+ "server.",
368
+
369
+ NULL
370
+};
371
+
372
static BlockDriver bdrv_nfs = {
373
.format_name = "nfs",
374
.protocol_name = "nfs",
375
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
376
.bdrv_refresh_filename = nfs_refresh_filename,
377
.bdrv_dirname = nfs_dirname,
378
379
+ .strong_runtime_opts = nfs_strong_runtime_opts,
380
+
381
#ifdef LIBNFS_FEATURE_PAGECACHE
382
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
383
#endif
384
diff --git a/block/null.c b/block/null.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/block/null.c
387
+++ b/block/null.c
388
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
389
bs->full_open_options = qobject_ref(opts);
390
}
391
392
+static const char *const null_strong_runtime_opts[] = {
393
+ BLOCK_OPT_SIZE,
394
+ NULL_OPT_ZEROES,
395
+
396
+ NULL
397
+};
398
+
399
static BlockDriver bdrv_null_co = {
400
.format_name = "null-co",
401
.protocol_name = "null-co",
402
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
403
.bdrv_co_block_status = null_co_block_status,
404
405
.bdrv_refresh_filename = null_refresh_filename,
406
+ .strong_runtime_opts = null_strong_runtime_opts,
407
};
408
409
static BlockDriver bdrv_null_aio = {
410
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
411
.bdrv_co_block_status = null_co_block_status,
412
413
.bdrv_refresh_filename = null_refresh_filename,
414
+ .strong_runtime_opts = null_strong_runtime_opts,
415
};
416
417
static void bdrv_null_init(void)
418
diff --git a/block/nvme.c b/block/nvme.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/nvme.c
421
+++ b/block/nvme.c
422
@@ -XXX,XX +XXX,XX @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host)
423
qemu_vfio_dma_unmap(s->vfio, host);
424
}
425
426
+static const char *const nvme_strong_runtime_opts[] = {
427
+ NVME_BLOCK_OPT_DEVICE,
428
+ NVME_BLOCK_OPT_NAMESPACE,
429
+
430
+ NULL
431
+};
432
+
433
static BlockDriver bdrv_nvme = {
434
.format_name = "nvme",
435
.protocol_name = "nvme",
436
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
437
438
.bdrv_refresh_filename = nvme_refresh_filename,
439
.bdrv_refresh_limits = nvme_refresh_limits,
440
+ .strong_runtime_opts = nvme_strong_runtime_opts,
441
442
.bdrv_detach_aio_context = nvme_detach_aio_context,
443
.bdrv_attach_aio_context = nvme_attach_aio_context,
444
diff --git a/block/qcow.c b/block/qcow.c
347
diff --git a/block/qcow.c b/block/qcow.c
445
index XXXXXXX..XXXXXXX 100644
348
index XXXXXXX..XXXXXXX 100644
446
--- a/block/qcow.c
349
--- a/block/qcow.c
447
+++ b/block/qcow.c
350
+++ b/block/qcow.c
448
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
351
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
449
}
352
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
450
};
353
encryptfmt = qdict_get_try_str(encryptopts, "format");
451
354
452
+static const char *const qcow_strong_runtime_opts[] = {
355
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
453
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
356
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
454
+
357
false, errp);
455
+ NULL
358
if (!bs->file) {
456
+};
359
ret = -EINVAL;
457
+
458
static BlockDriver bdrv_qcow = {
459
.format_name    = "qcow",
460
.instance_size    = sizeof(BDRVQcowState),
461
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
462
.bdrv_get_info = qcow_get_info,
463
464
.create_opts = &qcow_create_opts,
465
+ .strong_runtime_opts = qcow_strong_runtime_opts,
466
};
467
468
static void bdrv_qcow_init(void)
469
diff --git a/block/qcow2.c b/block/qcow2.c
360
diff --git a/block/qcow2.c b/block/qcow2.c
470
index XXXXXXX..XXXXXXX 100644
361
index XXXXXXX..XXXXXXX 100644
471
--- a/block/qcow2.c
362
--- a/block/qcow2.c
472
+++ b/block/qcow2.c
363
+++ b/block/qcow2.c
473
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
364
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
474
}
365
475
};
366
/* Open external data file */
476
367
s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file,
477
+static const char *const qcow2_strong_runtime_opts[] = {
368
- true, &local_err);
478
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
369
+ 0, true, &local_err);
479
+
370
if (local_err) {
480
+ NULL
371
error_propagate(errp, local_err);
481
+};
372
ret = -EINVAL;
482
+
373
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
483
BlockDriver bdrv_qcow2 = {
374
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
484
.format_name = "qcow2",
375
if (!s->data_file && s->image_data_file) {
485
.instance_size = sizeof(BDRVQcow2State),
376
s->data_file = bdrv_open_child(s->image_data_file, options,
486
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
377
- "data-file", bs, &child_file,
487
.bdrv_inactivate = qcow2_inactivate,
378
+ "data-file", bs, &child_file, 0,
488
379
false, errp);
489
.create_opts = &qcow2_create_opts,
380
if (!s->data_file) {
490
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
381
ret = -EINVAL;
491
.bdrv_co_check = qcow2_co_check,
382
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
492
.bdrv_amend_options = qcow2_amend_options,
383
.ret = -EINPROGRESS
493
384
};
385
386
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
387
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
388
false, errp);
389
if (!bs->file) {
390
return -EINVAL;
391
diff --git a/block/qed.c b/block/qed.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/block/qed.c
394
+++ b/block/qed.c
395
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
396
.ret = -EINPROGRESS
397
};
398
399
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
400
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
401
false, errp);
402
if (!bs->file) {
403
return -EINVAL;
494
diff --git a/block/quorum.c b/block/quorum.c
404
diff --git a/block/quorum.c b/block/quorum.c
495
index XXXXXXX..XXXXXXX 100644
405
index XXXXXXX..XXXXXXX 100644
496
--- a/block/quorum.c
406
--- a/block/quorum.c
497
+++ b/block/quorum.c
407
+++ b/block/quorum.c
498
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
408
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
499
return NULL;
409
assert(ret < 32);
500
}
410
501
411
s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
502
+static const char *const quorum_strong_runtime_opts[] = {
412
- &child_format, false, &local_err);
503
+ QUORUM_OPT_VOTE_THRESHOLD,
413
+ &child_format, 0, false, &local_err);
504
+ QUORUM_OPT_BLKVERIFY,
414
if (local_err) {
505
+ QUORUM_OPT_REWRITE,
415
ret = -EINVAL;
506
+ QUORUM_OPT_READ_PATTERN,
416
goto close_exit;
507
+
417
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
508
+ NULL
418
/* We can safely add the child now */
509
+};
419
bdrv_ref(child_bs);
510
+
420
511
static BlockDriver bdrv_quorum = {
421
- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, errp);
512
.format_name = "quorum",
422
+ child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp);
513
423
if (child == NULL) {
514
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
424
s->next_child_index--;
515
425
goto out;
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
426
diff --git a/block/raw-format.c b/block/raw-format.c
524
index XXXXXXX..XXXXXXX 100644
427
index XXXXXXX..XXXXXXX 100644
525
--- a/block/raw-format.c
428
--- a/block/raw-format.c
526
+++ b/block/raw-format.c
429
+++ b/block/raw-format.c
527
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
430
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
528
read_flags, write_flags);
431
BDRVRawState *s = bs->opaque;
529
}
432
int ret;
530
433
531
+static const char *const raw_strong_runtime_opts[] = {
434
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
532
+ "offset",
435
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
533
+ "size",
436
false, errp);
534
+
437
if (!bs->file) {
535
+ NULL
438
return -EINVAL;
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
439
diff --git a/block/replication.c b/block/replication.c
584
index XXXXXXX..XXXXXXX 100644
440
index XXXXXXX..XXXXXXX 100644
585
--- a/block/replication.c
441
--- a/block/replication.c
586
+++ b/block/replication.c
442
+++ b/block/replication.c
587
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
443
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
588
aio_context_release(aio_context);
444
const char *mode;
589
}
445
const char *top_id;
590
446
591
+static const char *const replication_strong_runtime_opts[] = {
447
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
592
+ REPLICATION_MODE,
448
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
593
+ REPLICATION_TOP_ID,
449
false, errp);
594
+
450
if (!bs->file) {
595
+ NULL
451
return -EINVAL;
596
+};
597
+
598
BlockDriver bdrv_replication = {
599
.format_name = "replication",
600
.instance_size = sizeof(BDRVReplicationState),
601
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_replication = {
602
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
603
604
.has_variable_length = true,
605
+ .strong_runtime_opts = replication_strong_runtime_opts,
606
};
607
608
static void bdrv_replication_init(void)
609
diff --git a/block/sheepdog.c b/block/sheepdog.c
610
index XXXXXXX..XXXXXXX 100644
611
--- a/block/sheepdog.c
612
+++ b/block/sheepdog.c
613
@@ -XXX,XX +XXX,XX @@ static QemuOptsList sd_create_opts = {
614
}
615
};
616
617
+static const char *const sd_strong_runtime_opts[] = {
618
+ "vdi",
619
+ "snap-id",
620
+ "tag",
621
+ "server.",
622
+
623
+ NULL
624
+};
625
+
626
static BlockDriver bdrv_sheepdog = {
627
.format_name = "sheepdog",
628
.protocol_name = "sheepdog",
629
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
630
.bdrv_attach_aio_context = sd_attach_aio_context,
631
632
.create_opts = &sd_create_opts,
633
+ .strong_runtime_opts = sd_strong_runtime_opts,
634
};
635
636
static BlockDriver bdrv_sheepdog_tcp = {
637
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
638
.bdrv_attach_aio_context = sd_attach_aio_context,
639
640
.create_opts = &sd_create_opts,
641
+ .strong_runtime_opts = sd_strong_runtime_opts,
642
};
643
644
static BlockDriver bdrv_sheepdog_unix = {
645
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
646
.bdrv_attach_aio_context = sd_attach_aio_context,
647
648
.create_opts = &sd_create_opts,
649
+ .strong_runtime_opts = sd_strong_runtime_opts,
650
};
651
652
static void bdrv_sheepdog_init(void)
653
diff --git a/block/ssh.c b/block/ssh.c
654
index XXXXXXX..XXXXXXX 100644
655
--- a/block/ssh.c
656
+++ b/block/ssh.c
657
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
658
return ssh_grow_file(s, offset, errp);
659
}
660
661
+static const char *const ssh_strong_runtime_opts[] = {
662
+ "host",
663
+ "port",
664
+ "path",
665
+ "user",
666
+ "host_key_check",
667
+ "server.",
668
+
669
+ NULL
670
+};
671
+
672
static BlockDriver bdrv_ssh = {
673
.format_name = "ssh",
674
.protocol_name = "ssh",
675
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
676
.bdrv_co_truncate = ssh_co_truncate,
677
.bdrv_co_flush_to_disk = ssh_co_flush,
678
.create_opts = &ssh_create_opts,
679
+ .strong_runtime_opts = ssh_strong_runtime_opts,
680
};
681
682
static void bdrv_ssh_init(void)
683
diff --git a/block/throttle.c b/block/throttle.c
452
diff --git a/block/throttle.c b/block/throttle.c
684
index XXXXXXX..XXXXXXX 100644
453
index XXXXXXX..XXXXXXX 100644
685
--- a/block/throttle.c
454
--- a/block/throttle.c
686
+++ b/block/throttle.c
455
+++ b/block/throttle.c
687
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs)
456
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
688
atomic_dec(&tgm->io_limits_disabled);
457
int ret;
689
}
458
690
459
bs->file = bdrv_open_child(NULL, options, "file", bs,
691
+static const char *const throttle_strong_runtime_opts[] = {
460
- &child_file, false, errp);
692
+ QEMU_OPT_THROTTLE_GROUP_NAME,
461
+ &child_file, 0, false, errp);
693
+
462
if (!bs->file) {
694
+ NULL
463
return -EINVAL;
695
+};
464
}
696
+
465
diff --git a/block/vdi.c b/block/vdi.c
697
static BlockDriver bdrv_throttle = {
466
index XXXXXXX..XXXXXXX 100644
698
.format_name = "throttle",
467
--- a/block/vdi.c
699
.instance_size = sizeof(ThrottleGroupMember),
468
+++ b/block/vdi.c
700
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
469
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
701
.bdrv_co_drain_end = throttle_co_drain_end,
470
Error *local_err = NULL;
702
471
QemuUUID uuid_link, uuid_parent;
703
.is_filter = true,
472
704
+ .strong_runtime_opts = throttle_strong_runtime_opts,
473
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
705
};
474
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
706
475
false, errp);
707
static void bdrv_throttle_init(void)
476
if (!bs->file) {
477
return -EINVAL;
478
diff --git a/block/vhdx.c b/block/vhdx.c
479
index XXXXXXX..XXXXXXX 100644
480
--- a/block/vhdx.c
481
+++ b/block/vhdx.c
482
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
483
uint64_t signature;
484
Error *local_err = NULL;
485
486
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
487
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
488
false, errp);
489
if (!bs->file) {
490
return -EINVAL;
491
diff --git a/block/vmdk.c b/block/vmdk.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/block/vmdk.c
494
+++ b/block/vmdk.c
495
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
496
assert(ret < 32);
497
498
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
499
- bs, &child_file, false, &local_err);
500
+ bs, &child_file, 0, false, &local_err);
501
g_free(extent_path);
502
if (local_err) {
503
error_propagate(errp, local_err);
504
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
505
uint32_t magic;
506
Error *local_err = NULL;
507
508
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
509
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
510
false, errp);
511
if (!bs->file) {
512
return -EINVAL;
708
diff --git a/block/vpc.c b/block/vpc.c
513
diff --git a/block/vpc.c b/block/vpc.c
709
index XXXXXXX..XXXXXXX 100644
514
index XXXXXXX..XXXXXXX 100644
710
--- a/block/vpc.c
515
--- a/block/vpc.c
711
+++ b/block/vpc.c
516
+++ b/block/vpc.c
712
@@ -XXX,XX +XXX,XX @@ static QemuOptsList vpc_create_opts = {
517
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
713
}
518
int ret;
714
};
519
int64_t bs_size;
715
520
716
+static const char *const vpc_strong_runtime_opts[] = {
521
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
717
+ VPC_OPT_SIZE_CALC,
522
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
718
+
523
false, errp);
719
+ NULL
524
if (!bs->file) {
720
+};
525
return -EINVAL;
721
+
722
static BlockDriver bdrv_vpc = {
723
.format_name = "vpc",
724
.instance_size = sizeof(BDRVVPCState),
725
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
726
727
.create_opts = &vpc_create_opts,
728
.bdrv_has_zero_init = vpc_has_zero_init,
729
+ .strong_runtime_opts = vpc_strong_runtime_opts,
730
};
731
732
static void bdrv_vpc_init(void)
733
diff --git a/block/vvfat.c b/block/vvfat.c
526
diff --git a/block/vvfat.c b/block/vvfat.c
734
index XXXXXXX..XXXXXXX 100644
527
index XXXXXXX..XXXXXXX 100644
735
--- a/block/vvfat.c
528
--- a/block/vvfat.c
736
+++ b/block/vvfat.c
529
+++ b/block/vvfat.c
737
@@ -XXX,XX +XXX,XX @@ static void vvfat_close(BlockDriverState *bs)
530
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
738
}
531
options = qdict_new();
532
qdict_put_str(options, "write-target.driver", "qcow");
533
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
534
- &child_vvfat_qcow, false, errp);
535
+ &child_vvfat_qcow, 0, false, errp);
536
qobject_unref(options);
537
if (!s->qcow) {
538
ret = -EINVAL;
539
diff --git a/blockjob.c b/blockjob.c
540
index XXXXXXX..XXXXXXX 100644
541
--- a/blockjob.c
542
+++ b/blockjob.c
543
@@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
544
if (job->job.aio_context != qemu_get_aio_context()) {
545
aio_context_release(job->job.aio_context);
546
}
547
- c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context,
548
- perm, shared_perm, job, errp);
549
+ c = bdrv_root_attach_child(bs, name, &child_job, 0,
550
+ job->job.aio_context, perm, shared_perm, job,
551
+ errp);
552
if (job->job.aio_context != qemu_get_aio_context()) {
553
aio_context_acquire(job->job.aio_context);
554
}
555
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
556
index XXXXXXX..XXXXXXX 100644
557
--- a/tests/test-bdrv-drain.c
558
+++ b/tests/test-bdrv-drain.c
559
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
560
561
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
562
&error_abort);
563
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
564
+ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
565
566
/* This child will be the one to pass to requests through to, and
567
* it will stall until a drain occurs */
568
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
569
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
570
/* Takes our reference to child_bs */
571
tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file,
572
- &error_abort);
573
+ 0, &error_abort);
574
575
/* This child is just there to be deleted
576
* (for detach_instead_of_delete == true) */
577
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
578
&error_abort);
579
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
580
+ bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
581
582
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
583
blk_insert_bs(blk, bs, &error_abort);
584
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
585
586
bdrv_ref(data->c);
587
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
588
- &child_file, &error_abort);
589
+ &child_file, 0, &error_abort);
739
}
590
}
740
591
741
+static const char *const vvfat_strong_runtime_opts[] = {
592
static void detach_by_parent_aio_cb(void *opaque, int ret)
742
+ "dir",
593
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
743
+ "fat-type",
594
/* Set child relationships */
744
+ "floppy",
595
bdrv_ref(b);
745
+ "label",
596
bdrv_ref(a);
746
+ "rw",
597
- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, &error_abort);
747
+
598
- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, &error_abort);
748
+ NULL
599
+ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
749
+};
600
+ &error_abort);
750
+
601
+ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0,
751
static BlockDriver bdrv_vvfat = {
602
+ &error_abort);
752
.format_name = "vvfat",
603
753
.protocol_name = "fat",
604
bdrv_ref(a);
754
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
605
bdrv_attach_child(parent_a, a, "PA-A",
755
.bdrv_co_preadv = vvfat_co_preadv,
606
by_parent_cb ? &child_file : &detach_by_driver_cb_class,
756
.bdrv_co_pwritev = vvfat_co_pwritev,
607
- &error_abort);
757
.bdrv_co_block_status = vvfat_co_block_status,
608
+ 0, &error_abort);
758
+
609
759
+ .strong_runtime_opts = vvfat_strong_runtime_opts,
610
g_assert_cmpint(parent_a->refcnt, ==, 1);
760
};
611
g_assert_cmpint(parent_b->refcnt, ==, 1);
761
612
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
762
static void bdrv_vvfat_init(void)
613
/* Takes the reference to chain[i - 1] */
763
diff --git a/block/vxhs.c b/block/vxhs.c
614
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
764
index XXXXXXX..XXXXXXX 100644
615
"chain", &chain_child_class,
765
--- a/block/vxhs.c
616
- &error_abort);
766
+++ b/block/vxhs.c
617
+ 0, &error_abort);
767
@@ -XXX,XX +XXX,XX @@ static int64_t vxhs_getlength(BlockDriverState *bs)
618
}
768
return vdisk_size;
619
}
769
}
620
770
621
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
771
+static const char *const vxhs_strong_runtime_opts[] = {
622
772
+ VXHS_OPT_VDISK_ID,
623
bdrv_ref(old_child_bs);
773
+ "tls-creds",
624
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
774
+ VXHS_OPT_HOST,
625
- &child_backing, &error_abort);
775
+ VXHS_OPT_PORT,
626
+ &child_backing, 0, &error_abort);
776
+ VXHS_OPT_SERVER".",
627
777
+
628
for (i = 0; i < old_drain_count; i++) {
778
+ NULL
629
bdrv_drained_begin(old_child_bs);
779
+};
630
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
780
+
631
index XXXXXXX..XXXXXXX 100644
781
static BlockDriver bdrv_vxhs = {
632
--- a/tests/test-bdrv-graph-mod.c
782
.format_name = "vxhs",
633
+++ b/tests/test-bdrv-graph-mod.c
783
.protocol_name = "vxhs",
634
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
784
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vxhs = {
635
785
.bdrv_getlength = vxhs_getlength,
636
blk_insert_bs(root, bs, &error_abort);
786
.bdrv_aio_preadv = vxhs_aio_preadv,
637
787
.bdrv_aio_pwritev = vxhs_aio_pwritev,
638
- bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
788
+ .strong_runtime_opts = vxhs_strong_runtime_opts,
639
+ bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort);
789
};
640
790
641
bdrv_append(filter, bs, &local_err);
791
static void bdrv_vxhs_init(void)
642
643
@@ -XXX,XX +XXX,XX @@ static void test_should_update_child(void)
644
bdrv_set_backing_hd(target, bs, &error_abort);
645
646
g_assert(target->backing->bs == bs);
647
- bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
648
+ bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort);
649
bdrv_append(filter, bs, &error_abort);
650
g_assert(target->backing->bs == bs);
651
792
--
652
--
793
2.20.1
653
2.25.4
794
654
795
655
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Currently, BlockDriver.bdrv_refresh_filename() is supposed to both
3
For now, all callers pass 0 and no callee evaluates this value. Later
4
refresh the filename (BDS.exact_filename) and set BDS.full_open_options.
4
patches will change both.
5
Now that we have generic code in the central bdrv_refresh_filename() for
6
creating BDS.full_open_options, we can drop the latter part from all
7
BlockDriver.bdrv_refresh_filename() implementations.
8
9
This also means that we can drop all of the existing default code for
10
this from the global bdrv_refresh_filename() itself.
11
12
Furthermore, we now have to call BlockDriver.bdrv_refresh_filename()
13
after having set BDS.full_open_options, because the block driver's
14
implementation should now be allowed to depend on BDS.full_open_options
15
being set correctly.
16
17
Finally, with this patch we can drop the @options parameter from
18
BlockDriver.bdrv_refresh_filename(); also, add a comment on this
19
function's purpose in block/block_int.h while touching its interface.
20
21
This completely obsoletes blklogwrite's implementation of
22
.bdrv_refresh_filename().
23
5
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
Message-id: 20190201192935.18394-25-mreitz@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200513110544.176672-7-mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
10
---
28
include/block/block_int.h | 6 +-
11
include/block/block_int.h | 5 ++++-
29
block.c | 131 +++++++------------------------------
12
block.c | 22 ++++++++++++----------
30
block/blkdebug.c | 54 ++++++---------
13
block/backup-top.c | 3 ++-
31
block/blklogwrites.c | 22 -------
14
block/blkdebug.c | 5 +++--
32
block/blkverify.c | 16 +----
15
block/blklogwrites.c | 9 +++++----
33
block/commit.c | 2 +-
16
block/commit.c | 1 +
34
block/mirror.c | 2 +-
17
block/copy-on-read.c | 1 +
35
block/nbd.c | 23 +------
18
block/mirror.c | 1 +
36
block/nfs.c | 36 +---------
19
block/quorum.c | 1 +
37
block/null.c | 22 ++++---
20
block/replication.c | 1 +
38
block/nvme.c | 22 ++++---
21
block/vvfat.c | 1 +
39
block/quorum.c | 30 ---------
22
tests/test-bdrv-drain.c | 5 +++--
40
tests/qemu-iotests/228 | 4 --
23
tests/test-bdrv-graph-mod.c | 1 +
41
tests/qemu-iotests/228.out | 2 +-
24
13 files changed, 36 insertions(+), 20 deletions(-)
42
14 files changed, 81 insertions(+), 291 deletions(-)
43
25
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
26
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
28
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
29
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
Error **errp);
31
* the parents in @parent_perm and @parent_shared.
50
int (*bdrv_make_empty)(BlockDriverState *bs);
32
*
51
33
* If @c is NULL, return the permissions for attaching a new child for the
52
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
34
- * given @child_class.
53
+ /*
35
+ * given @child_class and @role.
54
+ * Refreshes the bs->exact_filename field. If that is impossible,
36
*
55
+ * bs->exact_filename has to be left empty.
37
* If @reopen_queue is non-NULL, don't return the currently needed
56
+ */
38
* permissions, but those that will be needed after applying the
57
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
58
40
*/
59
/*
41
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
60
* Gathers the open options for all children into @target.
42
const BdrvChildClass *child_class,
43
+ BdrvChildRole role,
44
BlockReopenQueue *reopen_queue,
45
uint64_t parent_perm, uint64_t parent_shared,
46
uint64_t *nperm, uint64_t *nshared);
47
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
48
* all children */
49
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
50
const BdrvChildClass *child_class,
51
+ BdrvChildRole child_role,
52
BlockReopenQueue *reopen_queue,
53
uint64_t perm, uint64_t shared,
54
uint64_t *nperm, uint64_t *nshared);
55
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
56
* CONSISTENT_READ and doesn't share WRITE. */
57
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
58
const BdrvChildClass *child_class,
59
+ BdrvChildRole child_role,
60
BlockReopenQueue *reopen_queue,
61
uint64_t perm, uint64_t shared,
62
uint64_t *nperm, uint64_t *nshared);
61
diff --git a/block.c b/block.c
63
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
65
--- a/block.c
64
+++ b/block.c
66
+++ b/block.c
65
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
67
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
66
return found_any;
68
69
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
70
BdrvChild *c, const BdrvChildClass *child_class,
71
- BlockReopenQueue *reopen_queue,
72
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
73
uint64_t parent_perm, uint64_t parent_shared,
74
uint64_t *nperm, uint64_t *nshared)
75
{
76
assert(bs->drv && bs->drv->bdrv_child_perm);
77
- bs->drv->bdrv_child_perm(bs, c, child_class, reopen_queue,
78
+ bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue,
79
parent_perm, parent_shared,
80
nperm, nshared);
81
/* TODO Take force_share from reopen_queue */
82
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
83
uint64_t cur_perm, cur_shared;
84
bool child_tighten_restr;
85
86
- bdrv_child_perm(bs, c->bs, c, c->klass, q,
87
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q,
88
cumulative_perms, cumulative_shared_perms,
89
&cur_perm, &cur_shared);
90
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
91
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
92
/* Update all children */
93
QLIST_FOREACH(c, &bs->children, next) {
94
uint64_t cur_perm, cur_shared;
95
- bdrv_child_perm(bs, c->bs, c, c->klass, NULL,
96
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
97
cumulative_perms, cumulative_shared_perms,
98
&cur_perm, &cur_shared);
99
bdrv_child_set_perm(c, cur_perm, cur_shared);
100
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
101
uint64_t perms, shared;
102
103
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
104
- bdrv_child_perm(bs, c->bs, c, c->klass, NULL, parent_perms, parent_shared,
105
- &perms, &shared);
106
+ bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
107
+ parent_perms, parent_shared, &perms, &shared);
108
109
return bdrv_child_try_set_perm(c, perms, shared, errp);
67
}
110
}
68
111
69
-static bool append_open_options(QDict *d, BlockDriverState *bs)
112
void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
70
-{
113
const BdrvChildClass *child_class,
71
- const QDictEntry *entry;
114
+ BdrvChildRole role,
72
- QemuOptDesc *desc;
115
BlockReopenQueue *reopen_queue,
73
- bool found_any = false;
116
uint64_t perm, uint64_t shared,
74
-
117
uint64_t *nperm, uint64_t *nshared)
75
- for (entry = qdict_first(bs->options); entry;
118
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
76
- entry = qdict_next(bs->options, entry))
119
77
- {
120
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
78
- /* Exclude all non-driver-specific options */
121
const BdrvChildClass *child_class,
79
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
122
+ BdrvChildRole role,
80
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
123
BlockReopenQueue *reopen_queue,
81
- break;
124
uint64_t perm, uint64_t shared,
82
- }
125
uint64_t *nperm, uint64_t *nshared)
83
- }
126
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
84
- if (desc->name) {
127
85
- continue;
128
/* Apart from the modifications below, the same permissions are
86
- }
129
* forwarded and left alone as for filters */
87
-
130
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
88
- qdict_put_obj(d, qdict_entry_key(entry),
131
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
89
- qobject_ref(qdict_entry_value(entry)));
132
perm, shared, &perm, &shared);
90
- found_any = true;
133
91
- }
134
/* Format drivers may touch metadata even if the guest doesn't write */
92
-
135
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
93
- return found_any;
136
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
94
-}
137
95
-
138
assert(parent_bs->drv);
96
/* Note: This function may return false positives; it may return true
139
- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, NULL,
97
* even if opening the backing file specified by bs's image header
140
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL,
98
* would result in exactly bs->backing. */
141
perm, shared_perm, &perm, &shared_perm);
99
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
142
100
BdrvChild *child;
143
child = bdrv_root_attach_child(child_bs, child_name, child_class,
101
QDict *opts;
144
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
102
bool backing_overridden;
145
if (state->replace_backing_bs && state->new_backing_bs) {
103
+ bool generate_json_filename; /* Whether our default implementation should
146
uint64_t nperm, nshared;
104
+ fill exact_filename (false) or not (true) */
147
bdrv_child_perm(state->bs, state->new_backing_bs,
105
148
- NULL, &child_backing, bs_queue,
106
if (!drv) {
149
+ NULL, &child_backing, 0, bs_queue,
107
return;
150
state->perm, state->shared_perm,
108
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
151
&nperm, &nshared);
109
backing_overridden = false;
152
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
110
}
153
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
111
154
} else {
112
- if (drv->bdrv_refresh_filename) {
155
uint64_t nperm, nshared;
113
- /* Obsolete information is of no use here, so drop the old file name
156
114
- * information before refreshing it */
157
- bdrv_child_perm(parent->state.bs, bs, c, c->klass, q,
115
- bs->exact_filename[0] = '\0';
158
+ bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q,
116
- if (bs->full_open_options) {
159
parent->state.perm, parent->state.shared_perm,
117
- qobject_unref(bs->full_open_options);
160
&nperm, &nshared);
118
- bs->full_open_options = NULL;
161
119
- }
162
diff --git a/block/backup-top.c b/block/backup-top.c
120
-
163
index XXXXXXX..XXXXXXX 100644
121
- opts = qdict_new();
164
--- a/block/backup-top.c
122
- append_open_options(opts, bs);
165
+++ b/block/backup-top.c
123
- drv->bdrv_refresh_filename(bs, opts);
166
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
124
- qobject_unref(opts);
167
125
- } else if (bs->file) {
168
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
126
- /* Try to reconstruct valid information from the underlying file */
169
const BdrvChildClass *child_class,
127
- bool has_open_options;
170
+ BdrvChildRole role,
128
-
171
BlockReopenQueue *reopen_queue,
129
- bs->exact_filename[0] = '\0';
172
uint64_t perm, uint64_t shared,
130
- if (bs->full_open_options) {
173
uint64_t *nperm, uint64_t *nshared)
131
- qobject_unref(bs->full_open_options);
174
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
132
- bs->full_open_options = NULL;
175
*nperm = BLK_PERM_WRITE;
133
- }
134
-
135
- opts = qdict_new();
136
- has_open_options = append_open_options(opts, bs);
137
- has_open_options |= backing_overridden;
138
-
139
- /* If no specific options have been given for this BDS, the filename of
140
- * the underlying file should suffice for this one as well */
141
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
142
- strcpy(bs->exact_filename, bs->file->bs->exact_filename);
143
- }
144
- /* Reconstructing the full options QDict is simple for most format block
145
- * drivers, as long as the full options are known for the underlying
146
- * file BDS. The full options QDict of that file BDS should somehow
147
- * contain a representation of the filename, therefore the following
148
- * suffices without querying the (exact_)filename of this BDS. */
149
- if (bs->file->bs->full_open_options &&
150
- (!bs->backing || bs->backing->bs->full_open_options))
151
- {
152
- qdict_put_str(opts, "driver", drv->format_name);
153
- qdict_put(opts, "file",
154
- qobject_ref(bs->file->bs->full_open_options));
155
-
156
- if (bs->backing) {
157
- qdict_put(opts, "backing",
158
- qobject_ref(bs->backing->bs->full_open_options));
159
- } else if (backing_overridden) {
160
- qdict_put_null(opts, "backing");
161
- }
162
-
163
- bs->full_open_options = opts;
164
- } else {
165
- qobject_unref(opts);
166
- }
167
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
168
- /* There is no underlying file BDS (at least referenced by BDS.file),
169
- * so the full options QDict should be equal to the options given
170
- * specifically for this block device when it was opened (plus the
171
- * driver specification).
172
- * Because those options don't change, there is no need to update
173
- * full_open_options when it's already set. */
174
-
175
- opts = qdict_new();
176
- append_open_options(opts, bs);
177
- qdict_put_str(opts, "driver", drv->format_name);
178
-
179
- if (bs->exact_filename[0]) {
180
- /* This may not work for all block protocol drivers (some may
181
- * require this filename to be parsed), but we have to find some
182
- * default solution here, so just include it. If some block driver
183
- * does not support pure options without any filename at all or
184
- * needs some special format of the options QDict, it needs to
185
- * implement the driver-specific bdrv_refresh_filename() function.
186
- */
187
- qdict_put_str(opts, "filename", bs->exact_filename);
188
- }
189
-
190
- bs->full_open_options = opts;
191
- }
192
-
193
/* Gather the options QDict */
194
opts = qdict_new();
195
- append_strong_runtime_options(opts, bs);
196
+ generate_json_filename = append_strong_runtime_options(opts, bs);
197
+ generate_json_filename |= backing_overridden;
198
199
if (drv->bdrv_gather_child_options) {
200
/* Some block drivers may not want to present all of their children's
201
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
202
qobject_unref(bs->full_open_options);
203
bs->full_open_options = opts;
204
205
+ if (drv->bdrv_refresh_filename) {
206
+ /* Obsolete information is of no use here, so drop the old file name
207
+ * information before refreshing it */
208
+ bs->exact_filename[0] = '\0';
209
+
210
+ drv->bdrv_refresh_filename(bs);
211
+ } else if (bs->file) {
212
+ /* Try to reconstruct valid information from the underlying file */
213
+
214
+ bs->exact_filename[0] = '\0';
215
+
216
+ /* If no specific options have been given for this BDS, the filename of
217
+ * the underlying file should suffice for this one as well */
218
+ if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
219
+ strcpy(bs->exact_filename, bs->file->bs->exact_filename);
220
+ }
221
+ }
222
+
223
if (bs->exact_filename[0]) {
224
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
225
} else {
176
} else {
177
/* Source child */
178
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue,
179
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
180
perm, shared, nperm, nshared);
181
182
if (perm & BLK_PERM_WRITE) {
226
diff --git a/block/blkdebug.c b/block/blkdebug.c
183
diff --git a/block/blkdebug.c b/block/blkdebug.c
227
index XXXXXXX..XXXXXXX 100644
184
index XXXXXXX..XXXXXXX 100644
228
--- a/block/blkdebug.c
185
--- a/block/blkdebug.c
229
+++ b/block/blkdebug.c
186
+++ b/block/blkdebug.c
230
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
187
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
231
return bdrv_getlength(bs->file->bs);
188
232
}
189
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
233
190
const BdrvChildClass *child_class,
234
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
191
+ BdrvChildRole role,
235
+static void blkdebug_refresh_filename(BlockDriverState *bs)
192
BlockReopenQueue *reopen_queue,
193
uint64_t perm, uint64_t shared,
194
uint64_t *nperm, uint64_t *nshared)
236
{
195
{
237
BDRVBlkdebugState *s = bs->opaque;
196
BDRVBlkdebugState *s = bs->opaque;
238
- QDict *opts;
197
239
const QDictEntry *e;
198
- bdrv_filter_default_perms(bs, c, child_class, reopen_queue, perm, shared,
240
- bool force_json = false;
199
- nperm, nshared);
241
-
200
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
242
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
201
+ perm, shared, nperm, nshared);
243
- if (strcmp(qdict_entry_key(e), "config") &&
202
244
- strcmp(qdict_entry_key(e), "x-image"))
203
*nperm |= s->take_child_perms;
245
- {
204
*nshared &= ~s->unshare_child_perms;
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
205
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
303
index XXXXXXX..XXXXXXX 100644
206
index XXXXXXX..XXXXXXX 100644
304
--- a/block/blklogwrites.c
207
--- a/block/blklogwrites.c
305
+++ b/block/blklogwrites.c
208
+++ b/block/blklogwrites.c
306
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
209
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
307
return bdrv_getlength(bs->file->bs);
210
211
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
212
const BdrvChildClass *child_class,
213
+ BdrvChildRole role,
214
BlockReopenQueue *ro_q,
215
uint64_t perm, uint64_t shrd,
216
uint64_t *nperm, uint64_t *nshrd)
217
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
218
}
219
220
if (!strcmp(c->name, "log")) {
221
- bdrv_format_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
222
- nshrd);
223
+ bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
224
+ nperm, nshrd);
225
} else {
226
- bdrv_filter_default_perms(bs, c, child_class, ro_q, perm, shrd, nperm,
227
- nshrd);
228
+ bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
229
+ nperm, nshrd);
230
}
308
}
231
}
309
232
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
233
diff --git a/block/commit.c b/block/commit.c
373
index XXXXXXX..XXXXXXX 100644
234
index XXXXXXX..XXXXXXX 100644
374
--- a/block/commit.c
235
--- a/block/commit.c
375
+++ b/block/commit.c
236
+++ b/block/commit.c
376
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
237
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
377
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
238
378
}
239
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
379
240
const BdrvChildClass *child_class,
380
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
241
+ BdrvChildRole role,
381
+static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
242
BlockReopenQueue *reopen_queue,
382
{
243
uint64_t perm, uint64_t shared,
383
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
244
uint64_t *nperm, uint64_t *nshared)
384
bs->backing->bs->filename);
245
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/block/copy-on-read.c
248
+++ b/block/copy-on-read.c
249
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
250
251
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
252
const BdrvChildClass *child_class,
253
+ BdrvChildRole role,
254
BlockReopenQueue *reopen_queue,
255
uint64_t perm, uint64_t shared,
256
uint64_t *nperm, uint64_t *nshared)
385
diff --git a/block/mirror.c b/block/mirror.c
257
diff --git a/block/mirror.c b/block/mirror.c
386
index XXXXXXX..XXXXXXX 100644
258
index XXXXXXX..XXXXXXX 100644
387
--- a/block/mirror.c
259
--- a/block/mirror.c
388
+++ b/block/mirror.c
260
+++ b/block/mirror.c
389
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
261
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
390
NULL, 0);
262
391
}
263
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
392
264
const BdrvChildClass *child_class,
393
-static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
265
+ BdrvChildRole role,
394
+static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
266
BlockReopenQueue *reopen_queue,
395
{
267
uint64_t perm, uint64_t shared,
396
if (bs->backing == NULL) {
268
uint64_t *nperm, uint64_t *nshared)
397
/* we can be here after failed bdrv_attach_child in
398
diff --git a/block/nbd.c b/block/nbd.c
399
index XXXXXXX..XXXXXXX 100644
400
--- a/block/nbd.c
401
+++ b/block/nbd.c
402
@@ -XXX,XX +XXX,XX @@ static void nbd_attach_aio_context(BlockDriverState *bs,
403
nbd_client_attach_aio_context(bs, new_context);
404
}
405
406
-static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
407
+static void nbd_refresh_filename(BlockDriverState *bs)
408
{
409
BDRVNBDState *s = bs->opaque;
410
- QDict *opts = qdict_new();
411
- QObject *saddr_qdict;
412
- Visitor *ov;
413
const char *host = NULL, *port = NULL, *path = NULL;
414
415
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
416
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
417
path = s->saddr->u.q_unix.path;
418
} /* else can't represent as pseudo-filename */
419
420
- qdict_put_str(opts, "driver", "nbd");
421
-
422
if (path && s->export) {
423
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
424
"nbd+unix:///%s?socket=%s", s->export, path);
425
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
426
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
427
"nbd://%s:%s", host, port);
428
}
429
-
430
- ov = qobject_output_visitor_new(&saddr_qdict);
431
- visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
432
- visit_complete(ov, &saddr_qdict);
433
- visit_free(ov);
434
- qdict_put_obj(opts, "server", saddr_qdict);
435
-
436
- if (s->export) {
437
- qdict_put_str(opts, "export", s->export);
438
- }
439
- if (s->tlscredsid) {
440
- qdict_put_str(opts, "tls-creds", s->tlscredsid);
441
- }
442
-
443
- qdict_flatten(opts);
444
- bs->full_open_options = opts;
445
}
446
447
static char *nbd_dirname(BlockDriverState *bs, Error **errp)
448
diff --git a/block/nfs.c b/block/nfs.c
449
index XXXXXXX..XXXXXXX 100644
450
--- a/block/nfs.c
451
+++ b/block/nfs.c
452
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
453
return 0;
454
}
455
456
-static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
457
+static void nfs_refresh_filename(BlockDriverState *bs)
458
{
459
NFSClient *client = bs->opaque;
460
- QDict *opts = qdict_new();
461
- QObject *server_qdict;
462
- Visitor *ov;
463
-
464
- qdict_put_str(opts, "driver", "nfs");
465
466
if (client->uid && !client->gid) {
467
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
468
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
469
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
470
"nfs://%s%s", client->server->host, client->path);
471
}
472
-
473
- ov = qobject_output_visitor_new(&server_qdict);
474
- visit_type_NFSServer(ov, NULL, &client->server, &error_abort);
475
- visit_complete(ov, &server_qdict);
476
- qdict_put_obj(opts, "server", server_qdict);
477
- qdict_put_str(opts, "path", client->path);
478
-
479
- if (client->uid) {
480
- qdict_put_int(opts, "user", client->uid);
481
- }
482
- if (client->gid) {
483
- qdict_put_int(opts, "group", client->gid);
484
- }
485
- if (client->tcp_syncnt) {
486
- qdict_put_int(opts, "tcp-syn-cnt", client->tcp_syncnt);
487
- }
488
- if (client->readahead) {
489
- qdict_put_int(opts, "readahead-size", client->readahead);
490
- }
491
- if (client->pagecache) {
492
- qdict_put_int(opts, "page-cache-size", client->pagecache);
493
- }
494
- if (client->debug) {
495
- qdict_put_int(opts, "debug", client->debug);
496
- }
497
-
498
- visit_free(ov);
499
- qdict_flatten(opts);
500
- bs->full_open_options = opts;
501
}
502
503
static char *nfs_dirname(BlockDriverState *bs, Error **errp)
504
diff --git a/block/null.c b/block/null.c
505
index XXXXXXX..XXXXXXX 100644
506
--- a/block/null.c
507
+++ b/block/null.c
508
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn null_co_block_status(BlockDriverState *bs,
509
return ret;
510
}
511
512
-static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
513
+static void null_refresh_filename(BlockDriverState *bs)
514
{
515
- qdict_del(opts, "filename");
516
-
517
- if (!qdict_size(opts)) {
518
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
519
- bs->drv->format_name);
520
+ const QDictEntry *e;
521
+
522
+ for (e = qdict_first(bs->full_open_options); e;
523
+ e = qdict_next(bs->full_open_options, e))
524
+ {
525
+ /* These options can be ignored */
526
+ if (strcmp(qdict_entry_key(e), "filename") &&
527
+ strcmp(qdict_entry_key(e), "driver"))
528
+ {
529
+ return;
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
269
diff --git a/block/quorum.c b/block/quorum.c
577
index XXXXXXX..XXXXXXX 100644
270
index XXXXXXX..XXXXXXX 100644
578
--- a/block/quorum.c
271
--- a/block/quorum.c
579
+++ b/block/quorum.c
272
+++ b/block/quorum.c
580
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
273
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
581
bdrv_drained_end(bs);
274
275
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
276
const BdrvChildClass *child_class,
277
+ BdrvChildRole role,
278
BlockReopenQueue *reopen_queue,
279
uint64_t perm, uint64_t shared,
280
uint64_t *nperm, uint64_t *nshared)
281
diff --git a/block/replication.c b/block/replication.c
282
index XXXXXXX..XXXXXXX 100644
283
--- a/block/replication.c
284
+++ b/block/replication.c
285
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
286
287
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
288
const BdrvChildClass *child_class,
289
+ BdrvChildRole role,
290
BlockReopenQueue *reopen_queue,
291
uint64_t perm, uint64_t shared,
292
uint64_t *nperm, uint64_t *nshared)
293
diff --git a/block/vvfat.c b/block/vvfat.c
294
index XXXXXXX..XXXXXXX 100644
295
--- a/block/vvfat.c
296
+++ b/block/vvfat.c
297
@@ -XXX,XX +XXX,XX @@ err:
298
299
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
300
const BdrvChildClass *child_class,
301
+ BdrvChildRole role,
302
BlockReopenQueue *reopen_queue,
303
uint64_t perm, uint64_t shared,
304
uint64_t *nperm, uint64_t *nshared)
305
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
306
index XXXXXXX..XXXXXXX 100644
307
--- a/tests/test-bdrv-drain.c
308
+++ b/tests/test-bdrv-drain.c
309
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
310
311
static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
312
const BdrvChildClass *child_class,
313
+ BdrvChildRole role,
314
BlockReopenQueue *reopen_queue,
315
uint64_t perm, uint64_t shared,
316
uint64_t *nperm, uint64_t *nshared)
317
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
318
child_class = &child_file;
319
}
320
321
- bdrv_format_default_perms(bs, c, child_class, reopen_queue, perm, shared,
322
- nperm, nshared);
323
+ bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
324
+ perm, shared, nperm, nshared);
582
}
325
}
583
326
584
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
327
static int bdrv_test_change_backing_file(BlockDriverState *bs,
585
-{
328
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
586
- BDRVQuorumState *s = bs->opaque;
329
index XXXXXXX..XXXXXXX 100644
587
- QDict *opts;
330
--- a/tests/test-bdrv-graph-mod.c
588
- QList *children;
331
+++ b/tests/test-bdrv-graph-mod.c
589
- int i;
332
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
590
-
333
591
- for (i = 0; i < s->num_children; i++) {
334
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
592
- if (!s->children[i]->bs->full_open_options) {
335
const BdrvChildClass *child_class,
593
- return;
336
+ BdrvChildRole role,
594
- }
337
BlockReopenQueue *reopen_queue,
595
- }
338
uint64_t perm, uint64_t shared,
596
-
339
uint64_t *nperm, uint64_t *nshared)
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
--
340
--
653
2.20.1
341
2.25.4
654
342
655
343
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
bdrv_check_perm in it's recursion checks each node in context of new
3
For now, all callers (effectively) pass 0 and no callee evaluates thie
4
permissions for one parent, because of nature of DFS. It works well,
4
value. Later patches will change both.
5
while children subgraph of top-most updated node is a tree, i.e. it
5
6
doesn't have any kind of loops. But if we have a loop (not oriented,
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
of course), i.e. we have two different ways from top-node to some
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
child-node, then bdrv_check_perm will do wrong thing:
8
Message-Id: <20200513110544.176672-8-mreitz@redhat.com>
9
10
top
11
| \
12
| |
13
v v
14
A B
15
| |
16
v v
17
node
18
19
It will once check new permissions of node in context of new A
20
permissions and old B permissions and once visa-versa. It's a wrong way
21
and may lead to corruption of permission system. We may start with
22
no-permissions and all-shared for both A->node and B->node relations
23
and finish up with non shared write permission for both ways.
24
25
The following commit will add a test, which shows this bug.
26
27
To fix this situation, let's really set BdrvChild permissions during
28
bdrv_check_perm procedure. And we are happy here, as check-perm is
29
already written in transaction manner, so we just need to restore
30
backed-up permissions in _abort.
31
32
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
---
10
---
35
include/block/block_int.h | 5 +++++
11
include/block/block_int.h | 3 ++-
36
block.c | 27 ++++++++++++++++++++++++++-
12
block.c | 40 +++++++++++++++++++++++----------------
37
2 files changed, 31 insertions(+), 1 deletion(-)
13
block/block-backend.c | 3 ++-
14
block/vvfat.c | 3 ++-
15
4 files changed, 30 insertions(+), 19 deletions(-)
38
16
39
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
diff --git a/include/block/block_int.h b/include/block/block_int.h
40
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
41
--- a/include/block/block_int.h
19
--- a/include/block/block_int.h
42
+++ b/include/block/block_int.h
20
+++ b/include/block/block_int.h
43
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
21
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
44
*/
22
* non-BDS parents. */
45
uint64_t shared_perm;
23
bool parent_is_bds;
46
24
47
+ /* backup of permissions during permission update procedure */
25
- void (*inherit_options)(int *child_flags, QDict *child_options,
48
+ bool has_backup_perm;
26
+ void (*inherit_options)(BdrvChildRole role,
49
+ uint64_t backup_perm;
27
+ int *child_flags, QDict *child_options,
50
+ uint64_t backup_shared_perm;
28
int parent_flags, QDict *parent_options);
51
+
29
52
QLIST_ENTRY(BdrvChild) next;
30
void (*change_media)(BdrvChild *child, bool load);
53
QLIST_ENTRY(BdrvChild) next_parent;
54
};
55
diff --git a/block.c b/block.c
31
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
33
--- a/block.c
58
+++ b/block.c
34
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
35
@@ -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);
36
QDict *options, int flags,
61
g_slist_free(ignore_children);
37
BlockDriverState *parent,
62
38
const BdrvChildClass *child_class,
63
- return ret;
39
+ BdrvChildRole child_role,
64
+ if (ret < 0) {
40
Error **errp);
65
+ return ret;
41
66
+ }
42
/* If non-zero, use only whitelisted block drivers */
67
+
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
68
+ if (!c->has_backup_perm) {
44
* Returns the options and flags that bs->file should get if a protocol driver
69
+ c->has_backup_perm = true;
45
* is expected, based on the given options and flags for the parent BDS
70
+ c->backup_perm = c->perm;
46
*/
71
+ c->backup_shared_perm = c->shared_perm;
47
-static void bdrv_inherited_options(int *child_flags, QDict *child_options,
72
+ }
48
+static void bdrv_inherited_options(BdrvChildRole role,
73
+ /*
49
+ int *child_flags, QDict *child_options,
74
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
50
int parent_flags, QDict *parent_options)
75
+ * same child twice during check_perm procedure
51
{
76
+ */
52
int flags = parent_flags;
77
+
53
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
78
+ c->perm = perm;
54
* (and not only protocols) is permitted for it, based on the given options and
79
+ c->shared_perm = shared;
55
* flags for the parent BDS
80
+
56
*/
81
+ return 0;
57
-static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
58
+static void bdrv_inherited_fmt_options(BdrvChildRole role,
59
+ int *child_flags, QDict *child_options,
60
int parent_flags, QDict *parent_options)
61
{
62
- child_file.inherit_options(child_flags, child_options,
63
+ child_file.inherit_options(role, child_flags, child_options,
64
parent_flags, parent_options);
65
66
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
67
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
68
* Returns the options and flags that bs->backing should get, based on the
69
* given options and flags for the parent BDS
70
*/
71
-static void bdrv_backing_options(int *child_flags, QDict *child_options,
72
+static void bdrv_backing_options(BdrvChildRole role,
73
+ int *child_flags, QDict *child_options,
74
int parent_flags, QDict *parent_options)
75
{
76
int flags = parent_flags;
77
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
78
}
79
80
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
81
- &child_backing, errp);
82
+ &child_backing, 0, errp);
83
if (!backing_hd) {
84
bs->open_flags |= BDRV_O_NO_BACKING;
85
error_prepend(errp, "Could not open backing file: ");
86
@@ -XXX,XX +XXX,XX @@ free_exit:
87
static BlockDriverState *
88
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
89
BlockDriverState *parent, const BdrvChildClass *child_class,
90
- bool allow_none, Error **errp)
91
+ BdrvChildRole child_role, bool allow_none, Error **errp)
92
{
93
BlockDriverState *bs = NULL;
94
QDict *image_options;
95
@@ -XXX,XX +XXX,XX @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
96
}
97
98
bs = bdrv_open_inherit(filename, reference, image_options, 0,
99
- parent, child_class, errp);
100
+ parent, child_class, child_role, errp);
101
if (!bs) {
102
goto done;
103
}
104
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
105
BlockDriverState *bs;
106
107
bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
108
- allow_none, errp);
109
+ child_role, allow_none, errp);
110
if (bs == NULL) {
111
return NULL;
112
}
113
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
114
115
}
116
117
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
118
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
119
obj = NULL;
120
qobject_unref(obj);
121
visit_free(v);
122
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
123
QDict *options, int flags,
124
BlockDriverState *parent,
125
const BdrvChildClass *child_class,
126
+ BdrvChildRole child_role,
127
Error **errp)
128
{
129
int ret;
130
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
131
132
if (child_class) {
133
bs->inherits_from = parent;
134
- child_class->inherit_options(&flags, options,
135
+ child_class->inherit_options(child_role, &flags, options,
136
parent->open_flags, parent->options);
137
}
138
139
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
140
flags, options);
141
/* Let bdrv_backing_options() override "read-only" */
142
qdict_del(options, BDRV_OPT_READ_ONLY);
143
- bdrv_backing_options(&flags, options, flags, options);
144
+ bdrv_backing_options(0, &flags, options, flags, options);
145
}
146
147
bs->open_flags = flags;
148
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
149
BlockDriverState *file_bs;
150
151
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
152
- &child_file, true, &local_err);
153
+ &child_file, 0, true, &local_err);
154
if (local_err) {
155
goto fail;
156
}
157
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
158
QDict *options, int flags, Error **errp)
159
{
160
return bdrv_open_inherit(filename, reference, options, flags, NULL,
161
- NULL, errp);
162
+ NULL, 0, errp);
82
}
163
}
83
164
84
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
165
/* Return true if the NULL-terminated @list contains @str */
85
{
166
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
86
uint64_t cumulative_perms, cumulative_shared_perms;
167
BlockDriverState *bs,
87
168
QDict *options,
88
+ c->has_backup_perm = false;
169
const BdrvChildClass *klass,
89
+
170
+ BdrvChildRole role,
90
c->perm = perm;
171
QDict *parent_options,
91
c->shared_perm = shared;
172
int parent_flags,
92
173
bool keep_old_opts)
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
174
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
94
175
/* Inherit from parent node */
95
static void bdrv_child_abort_perm_update(BdrvChild *c)
176
if (parent_options) {
96
{
177
flags = 0;
97
+ if (c->has_backup_perm) {
178
- klass->inherit_options(&flags, options, parent_flags, parent_options);
98
+ c->perm = c->backup_perm;
179
+ klass->inherit_options(role, &flags, options,
99
+ c->shared_perm = c->backup_shared_perm;
180
+ parent_flags, parent_options);
100
+ c->has_backup_perm = false;
181
} else {
101
+ }
182
flags = bdrv_get_flags(bs);
102
+
183
}
103
bdrv_abort_perm_update(c->bs);
184
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
185
}
186
187
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
188
- child->klass, options, flags, child_keep_old);
189
+ child->klass, child->role, options, flags,
190
+ child_keep_old);
191
}
192
193
return bs_queue;
194
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
195
BlockDriverState *bs,
196
QDict *options, bool keep_old_opts)
197
{
198
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0,
199
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0,
200
keep_old_opts);
104
}
201
}
105
202
203
diff --git a/block/block-backend.c b/block/block-backend.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/block-backend.c
206
+++ b/block/block-backend.c
207
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, BlockBackend) block_backends =
208
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
209
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
210
211
-static void blk_root_inherit_options(int *child_flags, QDict *child_options,
212
+static void blk_root_inherit_options(BdrvChildRole role,
213
+ int *child_flags, QDict *child_options,
214
int parent_flags, QDict *parent_options)
215
{
216
/* We're not supposed to call this function for root nodes */
217
diff --git a/block/vvfat.c b/block/vvfat.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/vvfat.c
220
+++ b/block/vvfat.c
221
@@ -XXX,XX +XXX,XX @@ static BlockDriver vvfat_write_target = {
222
.bdrv_co_pwritev = write_target_commit,
223
};
224
225
-static void vvfat_qcow_options(int *child_flags, QDict *child_options,
226
+static void vvfat_qcow_options(BdrvChildRole role,
227
+ int *child_flags, QDict *child_options,
228
int parent_flags, QDict *parent_options)
229
{
230
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
106
--
231
--
107
2.20.1
232
2.25.4
108
233
109
234
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
As it already said in the comment, we don't want to create loops in
3
We plan to unify the generic .inherit_options() functions. The
4
parent->child relations. So, when we try to append @to to @c, we should
4
resulting common function will need to decide whether to force-enable
5
check that @c is not in @to children subtree, and we should check it
5
format probing, force-disable it, or leave it as-is. To make this
6
recursively, not only the first level. The patch provides BFS-based
6
decision, it will need to know whether the parent node is a format node
7
search, to check the relations.
7
or not (because we never want format probing if the parent is a format
8
node already (except for the backing chain)).
8
9
9
This is needed for further fleecing-hook filter usage: we need to
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
append it to source, when the hook is already a parent of target, and
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
source may be in a backing chain of target (fleecing-scheme). So, on
12
Message-Id: <20200513110544.176672-9-mreitz@redhat.com>
12
appending, the hook should not became a child (direct or through
13
children subtree) of the target.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
14
---
18
block.c | 43 +++++++++++++++++++++++++++++++++++++------
15
include/block/block_int.h | 2 +-
19
1 file changed, 37 insertions(+), 6 deletions(-)
16
block.c | 37 +++++++++++++++++++++++++++----------
17
block/block-backend.c | 2 +-
18
block/vvfat.c | 2 +-
19
4 files changed, 30 insertions(+), 13 deletions(-)
20
20
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
24
+++ b/include/block/block_int.h
25
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
26
* non-BDS parents. */
27
bool parent_is_bds;
28
29
- void (*inherit_options)(BdrvChildRole role,
30
+ void (*inherit_options)(BdrvChildRole role, bool parent_is_format,
31
int *child_flags, QDict *child_options,
32
int parent_flags, QDict *parent_options);
33
21
diff --git a/block.c b/block.c
34
diff --git a/block.c b/block.c
22
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
23
--- a/block.c
36
--- a/block.c
24
+++ b/block.c
37
+++ b/block.c
25
@@ -XXX,XX +XXX,XX @@ void bdrv_close_all(void)
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
26
39
* Returns the options and flags that bs->file should get if a protocol driver
27
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
40
* is expected, based on the given options and flags for the parent BDS
41
*/
42
-static void bdrv_inherited_options(BdrvChildRole role,
43
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
44
int *child_flags, QDict *child_options,
45
int parent_flags, QDict *parent_options)
28
{
46
{
29
- BdrvChild *to_c;
47
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
30
+ GQueue *queue;
48
* flags for the parent BDS
31
+ GHashTable *found;
49
*/
32
+ bool ret;
50
static void bdrv_inherited_fmt_options(BdrvChildRole role,
33
51
+ bool parent_is_format,
34
if (c->role->stay_at_node) {
52
int *child_flags, QDict *child_options,
35
return false;
53
int parent_flags, QDict *parent_options)
36
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
54
{
37
* if A is a child of B, that means we cannot replace A by B there
55
- child_file.inherit_options(role, child_flags, child_options,
38
* because that would create a loop. Silently detaching A from B
56
+ child_file.inherit_options(role, parent_is_format,
39
* is also not really an option. So overall just leaving A in
57
+ child_flags, child_options,
40
- * place there is the most sensible choice. */
58
parent_flags, parent_options);
41
- QLIST_FOREACH(to_c, &to->children, next) {
59
42
- if (to_c == c) {
60
*child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
43
- return false;
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
44
+ * place there is the most sensible choice.
62
* Returns the options and flags that bs->backing should get, based on the
45
+ *
63
* given options and flags for the parent BDS
46
+ * We would also create a loop in any cases where @c is only
64
*/
47
+ * indirectly referenced by @to. Prevent this by returning false
65
-static void bdrv_backing_options(BdrvChildRole role,
48
+ * if @c is found (by breadth-first search) anywhere in the whole
66
+static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
49
+ * subtree of @to.
67
int *child_flags, QDict *child_options,
50
+ */
68
int parent_flags, QDict *parent_options)
69
{
70
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
71
bs->explicit_options = qdict_clone_shallow(options);
72
73
if (child_class) {
74
+ bool parent_is_format;
51
+
75
+
52
+ ret = true;
76
+ if (parent->drv) {
53
+ found = g_hash_table_new(NULL, NULL);
77
+ parent_is_format = parent->drv->is_format;
54
+ g_hash_table_add(found, to);
78
+ } else {
55
+ queue = g_queue_new();
79
+ /*
56
+ g_queue_push_tail(queue, to);
80
+ * parent->drv is not set yet because this node is opened for
81
+ * (potential) format probing. That means that @parent is going
82
+ * to be a format node.
83
+ */
84
+ parent_is_format = true;
85
+ }
57
+
86
+
58
+ while (!g_queue_is_empty(queue)) {
87
bs->inherits_from = parent;
59
+ BlockDriverState *v = g_queue_pop_head(queue);
88
- child_class->inherit_options(child_role, &flags, options,
60
+ BdrvChild *c2;
89
+ child_class->inherit_options(child_role, parent_is_format,
61
+
90
+ &flags, options,
62
+ QLIST_FOREACH(c2, &v->children, next) {
91
parent->open_flags, parent->options);
63
+ if (c2 == c) {
92
}
64
+ ret = false;
93
65
+ break;
94
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
66
+ }
95
flags, options);
67
+
96
/* Let bdrv_backing_options() override "read-only" */
68
+ if (g_hash_table_contains(found, c2->bs)) {
97
qdict_del(options, BDRV_OPT_READ_ONLY);
69
+ continue;
98
- bdrv_backing_options(0, &flags, options, flags, options);
70
+ }
99
+ bdrv_backing_options(0, true, &flags, options, flags, options);
71
+
100
}
72
+ g_queue_push_tail(queue, c2->bs);
101
73
+ g_hash_table_add(found, c2->bs);
102
bs->open_flags = flags;
103
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
104
QDict *options,
105
const BdrvChildClass *klass,
106
BdrvChildRole role,
107
+ bool parent_is_format,
108
QDict *parent_options,
109
int parent_flags,
110
bool keep_old_opts)
111
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
112
/* Inherit from parent node */
113
if (parent_options) {
114
flags = 0;
115
- klass->inherit_options(role, &flags, options,
116
+ klass->inherit_options(role, parent_is_format, &flags, options,
117
parent_flags, parent_options);
118
} else {
119
flags = bdrv_get_flags(bs);
120
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
74
}
121
}
122
123
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
124
- child->klass, child->role, options, flags,
125
- child_keep_old);
126
+ child->klass, child->role, bs->drv->is_format,
127
+ options, flags, child_keep_old);
75
}
128
}
76
129
77
- return true;
130
return bs_queue;
78
+ g_queue_free(queue);
131
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
79
+ g_hash_table_destroy(found);
132
BlockDriverState *bs,
80
+
133
QDict *options, bool keep_old_opts)
81
+ return ret;
134
{
135
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, NULL, 0,
136
- keep_old_opts);
137
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
138
+ NULL, 0, keep_old_opts);
82
}
139
}
83
140
84
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
141
/*
142
diff --git a/block/block-backend.c b/block/block-backend.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/block/block-backend.c
145
+++ b/block/block-backend.c
146
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, BlockBackend) block_backends =
147
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
148
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
149
150
-static void blk_root_inherit_options(BdrvChildRole role,
151
+static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format,
152
int *child_flags, QDict *child_options,
153
int parent_flags, QDict *parent_options)
154
{
155
diff --git a/block/vvfat.c b/block/vvfat.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/block/vvfat.c
158
+++ b/block/vvfat.c
159
@@ -XXX,XX +XXX,XX @@ static BlockDriver vvfat_write_target = {
160
.bdrv_co_pwritev = write_target_commit,
161
};
162
163
-static void vvfat_qcow_options(BdrvChildRole role,
164
+static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
165
int *child_flags, QDict *child_options,
166
int parent_flags, QDict *parent_options)
167
{
85
--
168
--
86
2.20.1
169
2.25.4
87
170
88
171
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
If a format BDS's file BDS is in turn a format BDS, we cannot simply use
3
The other two .inherit_options implementations specify exactly for what
4
the same filename, because when opening a BDS tree based on a filename
4
case they are used in their name, so do it for this one as well.
5
alone, qemu will create only one format node on top of one protocol node
5
6
(disregarding a potential backing file).
6
(The actual intention behind this patch is to follow it up with a
7
generic bdrv_inherited_options() that works for all three cases.)
7
8
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-id: 20190201192935.18394-26-mreitz@redhat.com
11
Message-Id: <20200513110544.176672-10-mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block.c | 18 +++++++++++++++---
14
block.c | 8 ++++----
14
1 file changed, 15 insertions(+), 3 deletions(-)
15
1 file changed, 4 insertions(+), 4 deletions(-)
15
16
16
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
--- a/block.c
19
+++ b/block.c
20
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
21
22
* Returns the options and flags that bs->file should get if a protocol driver
22
bs->exact_filename[0] = '\0';
23
* is expected, based on the given options and flags for the parent BDS
23
24
*/
24
- /* If no specific options have been given for this BDS, the filename of
25
-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
25
- * the underlying file should suffice for this one as well */
26
- int *child_flags, QDict *child_options,
26
- if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
27
- int parent_flags, QDict *parent_options)
27
+ /*
28
+static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
28
+ * We can use the underlying file's filename if:
29
+ int *child_flags, QDict *child_options,
29
+ * - it has a filename,
30
+ int parent_flags, QDict *parent_options)
30
+ * - the file is a protocol BDS, and
31
{
31
+ * - opening that file (as this BDS's format) will automatically create
32
int flags = parent_flags;
32
+ * the BDS tree we have right now, that is:
33
33
+ * - the user did not significantly change this BDS's behavior with
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
34
+ * some explicit (strong) options
35
const BdrvChildClass child_file = {
35
+ * - no non-file child of this BDS has been overridden by the user
36
.parent_is_bds = true,
36
+ * Both of these conditions are represented by generate_json_filename.
37
.get_parent_desc = bdrv_child_get_parent_desc,
37
+ */
38
- .inherit_options = bdrv_inherited_options,
38
+ if (bs->file->bs->exact_filename[0] &&
39
+ .inherit_options = bdrv_protocol_options,
39
+ bs->file->bs->drv->bdrv_file_open &&
40
.drained_begin = bdrv_child_cb_drained_begin,
40
+ !generate_json_filename)
41
.drained_poll = bdrv_child_cb_drained_poll,
41
+ {
42
.drained_end = bdrv_child_cb_drained_end,
42
strcpy(bs->exact_filename, bs->file->bs->exact_filename);
43
}
44
}
45
--
43
--
46
2.20.1
44
2.25.4
47
45
48
46
diff view generated by jsdifflib
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Adds a fast path on aio context setting preventing
3
After the series this patch belongs to, we want to have a common
4
unnecessary context setting routine.
4
BdrvChildClass that encompasses all of child_file, child_format, and
5
Also, it prevents issues with cyclic walk of child
5
child_backing. Such a single class needs a single .inherit_options()
6
bds-es appeared because of registering aio walking
6
implementation, and this patch introduces it.
7
notifiers:
8
7
9
Call stack:
8
The next patch will show how the existing implementations can fall back
9
to it just by passing appropriate BdrvChildRole and parent_is_format
10
values.
10
11
11
0 __GI_raise
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
1 __GI_abort
13
Message-Id: <20200513110544.176672-11-mreitz@redhat.com>
13
2 __assert_fail_base
14
Reviewed-by: Eric Blake <eblake@redhat.com>
14
3 __GI___assert_fail
15
4 bdrv_detach_aio_context (bs=0x55f54d65c000) <<<
16
5 bdrv_detach_aio_context (bs=0x55f54fc8a800)
17
6 bdrv_set_aio_context (bs=0x55f54fc8a800, ...)
18
7 block_job_attached_aio_context
19
8 bdrv_attach_aio_context (bs=0x55f54d65c000, ...) <<<
20
9 bdrv_set_aio_context (bs=0x55f54d65c000)
21
10 blk_set_aio_context
22
11 virtio_blk_data_plane_stop
23
12 virtio_bus_stop_ioeventfd
24
13 virtio_vmstate_change
25
14 vm_state_notify (running=0, state=RUN_STATE_SHUTDOWN)
26
15 do_vm_stop (state=RUN_STATE_SHUTDOWN, send_stop=true)
27
16 vm_stop (state=RUN_STATE_SHUTDOWN)
28
17 main_loop_should_exit
29
18 main_loop
30
19 main
31
32
This can happen because of "new" context attachment to VM disk bds.
33
When attaching a new context the corresponding aio context handler is
34
called for each of aio_notifiers registered on the VM disk bds context.
35
Among those handlers, there is the block_job_attached_aio_context handler
36
which sets a new aio context for the block job bds. When doing so,
37
the old context is detached from all the block job bds children and one of
38
them is the VM disk bds, serving as backing store for the blockjob bds,
39
although the VM disk bds is actually the initializer of that process.
40
Since the VM disk bds is protected with walking_aio_notifiers flag
41
from double processing in recursive calls, the assert fires.
42
43
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
44
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
45
---
16
---
46
block.c | 4 ++++
17
block.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
47
1 file changed, 4 insertions(+)
18
1 file changed, 81 insertions(+)
48
19
49
diff --git a/block.c b/block.c
20
diff --git a/block.c b/block.c
50
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
51
--- a/block.c
22
--- a/block.c
52
+++ b/block.c
23
+++ b/block.c
53
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
24
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
54
{
25
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
55
AioContext *ctx = bdrv_get_aio_context(bs);
26
};
56
27
57
+ if (ctx == new_context) {
28
+/*
58
+ return;
29
+ * Returns the options and flags that a generic child of a BDS should
30
+ * get, based on the given options and flags for the parent BDS.
31
+ */
32
+static void __attribute__((unused))
33
+ bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
34
+ int *child_flags, QDict *child_options,
35
+ int parent_flags, QDict *parent_options)
36
+{
37
+ int flags = parent_flags;
38
+
39
+ /*
40
+ * First, decide whether to set, clear, or leave BDRV_O_PROTOCOL.
41
+ * Generally, the question to answer is: Should this child be
42
+ * format-probed by default?
43
+ */
44
+
45
+ /*
46
+ * Pure and non-filtered data children of non-format nodes should
47
+ * be probed by default (even when the node itself has BDRV_O_PROTOCOL
48
+ * set). This only affects a very limited set of drivers (namely
49
+ * quorum and blkverify when this comment was written).
50
+ * Force-clear BDRV_O_PROTOCOL then.
51
+ */
52
+ if (!parent_is_format &&
53
+ (role & BDRV_CHILD_DATA) &&
54
+ !(role & (BDRV_CHILD_METADATA | BDRV_CHILD_FILTERED)))
55
+ {
56
+ flags &= ~BDRV_O_PROTOCOL;
59
+ }
57
+ }
60
+
58
+
61
aio_disable_external(ctx);
59
+ /*
62
bdrv_parent_drained_begin(bs, NULL, false);
60
+ * All children of format nodes (except for COW children) and all
63
bdrv_drain(bs); /* ensure there are no in-flight requests */
61
+ * metadata children in general should never be format-probed.
62
+ * Force-set BDRV_O_PROTOCOL then.
63
+ */
64
+ if ((parent_is_format && !(role & BDRV_CHILD_COW)) ||
65
+ (role & BDRV_CHILD_METADATA))
66
+ {
67
+ flags |= BDRV_O_PROTOCOL;
68
+ }
69
+
70
+ /*
71
+ * If the cache mode isn't explicitly set, inherit direct and no-flush from
72
+ * the parent.
73
+ */
74
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
75
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
76
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
77
+
78
+ if (role & BDRV_CHILD_COW) {
79
+ /* backing files are opened read-only by default */
80
+ qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
81
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
82
+ } else {
83
+ /* Inherit the read-only option from the parent if it's not set */
84
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
85
+ qdict_copy_default(child_options, parent_options,
86
+ BDRV_OPT_AUTO_READ_ONLY);
87
+ }
88
+
89
+ /*
90
+ * bdrv_co_pdiscard() respects unmap policy for the parent, so we
91
+ * can default to enable it on lower layers regardless of the
92
+ * parent option.
93
+ */
94
+ qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
95
+
96
+ /* Clear flags that only apply to the top layer */
97
+ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
98
+
99
+ if (role & BDRV_CHILD_METADATA) {
100
+ flags &= ~BDRV_O_NO_IO;
101
+ }
102
+ if (role & BDRV_CHILD_COW) {
103
+ flags &= ~BDRV_O_TEMPORARY;
104
+ }
105
+
106
+ *child_flags = flags;
107
+}
108
+
109
static int bdrv_open_flags(BlockDriverState *bs, int flags)
110
{
111
int open_flags = flags;
64
--
112
--
65
2.20.1
113
2.25.4
66
114
67
115
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Currently, nvme's bdrv_refresh_filename() is an exact copy of null's
3
Let child_file's, child_format's, and child_backing's .inherit_options()
4
implementation. However, for null, "null-co://" and "null-aio://" are
4
implementations fall back to bdrv_inherited_options() to show that it
5
indeed valid filenames -- for nvme, they are not, as a device address is
5
would really work for all of these cases, if only the parents passed the
6
still required.
6
appropriate BdrvChildRole and parent_is_format values.
7
7
8
The correct implementation should generate a filename of the form
8
(Also, make bdrv_open_inherit(), the only place to explicitly call
9
"nvme://[PCI address]/[namespace]" (as the comment above
9
bdrv_backing_options(), call bdrv_inherited_options() instead.)
10
nvme_parse_filename() describes).
10
11
This patch should incur only two visible changes, both for child_format
12
children, both of which are effectively bug fixes:
13
14
First, they no longer have discard=unmap set by default. This reason it
15
was set is because bdrv_inherited_fmt_options() fell through to
16
bdrv_protocol_options(), and that set it because "format drivers take
17
care to send flushes and respect unmap policy". None of the drivers
18
that use child_format for their children (quorum and blkverify) are
19
format drivers, though, so this reasoning does not apply here.
20
21
Second, they no longer have BDRV_O_NO_IO force-cleared. child_format
22
was used solely for children that do not store any metadata and as such
23
will not be accessed by their parents as long as those parents do not
24
receive I/O themselves. Thus, such children should inherit
25
BDRV_O_NO_IO.
11
26
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Alberto Garcia <berto@igalia.com>
28
Message-Id: <20200513110544.176672-12-mreitz@redhat.com>
14
Message-id: 20190201192935.18394-27-mreitz@redhat.com
29
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
31
---
17
block/nvme.c | 23 +++++++++--------------
32
block.c | 71 +++++++++++++++------------------------------------------
18
1 file changed, 9 insertions(+), 14 deletions(-)
33
1 file changed, 19 insertions(+), 52 deletions(-)
19
34
20
diff --git a/block/nvme.c b/block/nvme.c
35
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
22
--- a/block/nvme.c
37
--- a/block.c
23
+++ b/block/nvme.c
38
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
39
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
25
40
BdrvChildRole child_role,
26
/* Total size of mapped qiov, accessed under dma_map_lock */
41
Error **errp);
27
int dma_map_count;
42
43
+/* TODO: Remove when no longer needed */
44
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
45
+ int *child_flags, QDict *child_options,
46
+ int parent_flags, QDict *parent_options);
28
+
47
+
29
+ /* PCI address (required for nvme_refresh_filename()) */
48
/* If non-zero, use only whitelisted block drivers */
30
+ char *device;
49
static int use_bdrv_whitelist;
31
} BDRVNVMeState;
50
32
51
@@ -XXX,XX +XXX,XX @@ static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
33
#define NVME_BLOCK_OPT_DEVICE "device"
52
int *child_flags, QDict *child_options,
34
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
53
int parent_flags, QDict *parent_options)
35
54
{
36
qemu_co_mutex_init(&s->dma_map_lock);
55
- int flags = parent_flags;
37
qemu_co_queue_init(&s->dma_flush_queue);
56
-
38
+ s->device = g_strdup(device);
57
- /* Enable protocol handling, disable format probing for bs->file */
39
s->nsid = namespace;
58
- flags |= BDRV_O_PROTOCOL;
40
s->aio_context = bdrv_get_aio_context(bs);
59
-
41
ret = event_notifier_init(&s->irq_notifier, 0);
60
- /* If the cache mode isn't explicitly set, inherit direct and no-flush from
42
@@ -XXX,XX +XXX,XX @@ static void nvme_close(BlockDriverState *bs)
61
- * the parent. */
43
event_notifier_cleanup(&s->irq_notifier);
62
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
44
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
63
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
45
qemu_vfio_close(s->vfio);
64
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
46
+
65
-
47
+ g_free(s->device);
66
- /* Inherit the read-only option from the parent if it's not set */
67
- qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
68
- qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
69
-
70
- /* Our block drivers take care to send flushes and respect unmap policy,
71
- * so we can default to enable both on lower layers regardless of the
72
- * corresponding parent options. */
73
- qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
74
-
75
- /* Clear flags that only apply to the top layer */
76
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ |
77
- BDRV_O_NO_IO);
78
-
79
- *child_flags = flags;
80
+ bdrv_inherited_options(BDRV_CHILD_IMAGE, true,
81
+ child_flags, child_options,
82
+ parent_flags, parent_options);
48
}
83
}
49
84
50
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
85
const BdrvChildClass child_file = {
51
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
86
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_fmt_options(BdrvChildRole role,
52
87
int *child_flags, QDict *child_options,
53
static void nvme_refresh_filename(BlockDriverState *bs)
88
int parent_flags, QDict *parent_options)
54
{
89
{
55
- const QDictEntry *e;
90
- child_file.inherit_options(role, parent_is_format,
91
- child_flags, child_options,
92
- parent_flags, parent_options);
56
-
93
-
57
- for (e = qdict_first(bs->full_open_options); e;
94
- *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
58
- e = qdict_next(bs->full_open_options, e))
95
+ bdrv_inherited_options(BDRV_CHILD_DATA, false,
59
- {
96
+ child_flags, child_options,
60
- /* These options can be ignored */
97
+ parent_flags, parent_options);
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
}
98
}
74
99
75
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
100
const BdrvChildClass child_format = {
101
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
102
int *child_flags, QDict *child_options,
103
int parent_flags, QDict *parent_options)
104
{
105
- int flags = parent_flags;
106
-
107
- /* The cache mode is inherited unmodified for backing files; except WCE,
108
- * which is only applied on the top level (BlockBackend) */
109
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
110
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
111
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
112
-
113
- /* backing files always opened read-only */
114
- qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
115
- qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
116
- flags &= ~BDRV_O_COPY_ON_READ;
117
-
118
- /* snapshot=on is handled on the top layer */
119
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
120
-
121
- *child_flags = flags;
122
+ bdrv_inherited_options(BDRV_CHILD_COW, true,
123
+ child_flags, child_options,
124
+ parent_flags, parent_options);
125
}
126
127
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
128
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
129
* Returns the options and flags that a generic child of a BDS should
130
* get, based on the given options and flags for the parent BDS.
131
*/
132
-static void __attribute__((unused))
133
- bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
134
- int *child_flags, QDict *child_options,
135
- int parent_flags, QDict *parent_options)
136
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
137
+ int *child_flags, QDict *child_options,
138
+ int parent_flags, QDict *parent_options)
139
{
140
int flags = parent_flags;
141
142
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
143
flags, options);
144
/* Let bdrv_backing_options() override "read-only" */
145
qdict_del(options, BDRV_OPT_READ_ONLY);
146
- bdrv_backing_options(0, true, &flags, options, flags, options);
147
+ bdrv_inherited_options(BDRV_CHILD_COW, true,
148
+ &flags, options, flags, options);
149
}
150
151
bs->open_flags = flags;
76
--
152
--
77
2.20.1
153
2.25.4
78
154
79
155
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
bdrv_find_backing_image() should use bdrv_get_full_backing_filename() or
3
Make bdrv_child_cb_attach() call bdrv_backing_attach() for children with
4
bdrv_make_absolute_filename() instead of trying to do what those
4
a COW role (and drop the reverse call from bdrv_backing_attach()), so it
5
functions do by itself.
5
can be used for any child (with a proper role set).
6
6
7
path_combine_deprecated() can now be dropped, so let's do that.
7
Because so far no child has a proper role set, we need a temporary new
8
callback for child_backing.attach that ensures bdrv_backing_attach() is
9
called for all COW children that do not have their role set yet.
10
11
(Also, move bdrv_child_cb_attach() down to group it with
12
bdrv_inherited_options().)
8
13
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Message-Id: <20200513110544.176672-13-mreitz@redhat.com>
11
Message-id: 20190201192935.18394-14-mreitz@redhat.com
16
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
18
---
14
block.c | 33 ++++++++++-----------------------
19
block.c | 27 ++++++++++++++++++++-------
15
1 file changed, 10 insertions(+), 23 deletions(-)
20
1 file changed, 20 insertions(+), 7 deletions(-)
16
21
17
diff --git a/block.c b/block.c
22
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
24
--- a/block.c
20
+++ b/block.c
25
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *path_combine(const char *base_path, const char *filename)
26
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
22
return result;
27
static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
28
int *child_flags, QDict *child_options,
29
int parent_flags, QDict *parent_options);
30
+static void bdrv_child_cb_attach(BdrvChild *child);
31
32
/* If non-zero, use only whitelisted block drivers */
33
static int use_bdrv_whitelist;
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child,
35
bdrv_drained_end_no_poll(bs, drained_end_counter);
23
}
36
}
24
37
25
-static void path_combine_deprecated(char *dest, int dest_size,
38
-static void bdrv_child_cb_attach(BdrvChild *child)
26
- const char *base_path,
27
- const char *filename)
28
-{
39
-{
29
- char *combined = path_combine(base_path, filename);
40
- BlockDriverState *bs = child->opaque;
30
- pstrcpy(dest, dest_size, combined);
41
- bdrv_apply_subtree_drain(child, bs);
31
- g_free(combined);
32
-}
42
-}
33
-
43
-
34
/*
44
static void bdrv_child_cb_detach(BdrvChild *child)
35
* Helper function for bdrv_parse_filename() implementations to remove optional
45
{
36
* protocol prefixes (especially "file:") from a filename and for putting the
46
BlockDriverState *bs = child->opaque;
37
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
47
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
38
48
parent->backing_blocker);
39
filename_full = g_malloc(PATH_MAX);
49
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
40
backing_file_full = g_malloc(PATH_MAX);
50
parent->backing_blocker);
41
- filename_tmp = g_malloc(PATH_MAX);
51
+}
42
52
43
is_protocol = path_has_protocol(backing_file);
53
+/* XXX: Will be removed along with child_backing */
44
54
+static void bdrv_child_cb_attach_backing(BdrvChild *c)
45
- /* This will recursively refresh everything in the backing chain */
55
+{
46
- bdrv_refresh_filename(bs);
56
+ if (!(c->role & BDRV_CHILD_COW)) {
47
-
57
+ bdrv_backing_attach(c);
48
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
58
+ }
49
59
bdrv_child_cb_attach(c);
50
/* If either of the filename paths is actually a protocol, then
51
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
52
} else {
53
/* If not an absolute filename path, make it relative to the current
54
* image's filename path */
55
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
56
- backing_file);
57
-
58
- /* We are going to compare absolute pathnames */
59
- if (!realpath(filename_tmp, filename_full)) {
60
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
61
+ NULL);
62
+ /* We are going to compare canonicalized absolute pathnames */
63
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
64
+ g_free(filename_tmp);
65
continue;
66
}
67
+ g_free(filename_tmp);
68
69
/* We need to make sure the backing filename we are comparing against
70
* is relative to the current image filename (or absolute) */
71
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
72
- curr_bs->backing_file);
73
-
74
- if (!realpath(filename_tmp, backing_file_full)) {
75
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
76
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
77
+ g_free(filename_tmp);
78
continue;
79
}
80
+ g_free(filename_tmp);
81
82
if (strcmp(backing_file_full, filename_full) == 0) {
83
retval = curr_bs->backing->bs;
84
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
85
86
g_free(filename_full);
87
g_free(backing_file_full);
88
- g_free(filename_tmp);
89
return retval;
90
}
60
}
91
61
62
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
63
const BdrvChildClass child_backing = {
64
.parent_is_bds = true,
65
.get_parent_desc = bdrv_child_get_parent_desc,
66
- .attach = bdrv_backing_attach,
67
+ .attach = bdrv_child_cb_attach_backing,
68
.detach = bdrv_backing_detach,
69
.inherit_options = bdrv_backing_options,
70
.drained_begin = bdrv_child_cb_drained_begin,
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
72
*child_flags = flags;
73
}
74
75
+static void bdrv_child_cb_attach(BdrvChild *child)
76
+{
77
+ BlockDriverState *bs = child->opaque;
78
+
79
+ if (child->role & BDRV_CHILD_COW) {
80
+ bdrv_backing_attach(child);
81
+ }
82
+
83
+ bdrv_apply_subtree_drain(child, bs);
84
+}
85
+
86
static int bdrv_open_flags(BlockDriverState *bs, int flags)
87
{
88
int open_flags = flags;
92
--
89
--
93
2.20.1
90
2.25.4
94
91
95
92
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This is a general function for making a filename that is relative to a
3
Make bdrv_child_cb_detach() call bdrv_backing_detach() for children with
4
certain BDS absolute.
4
a COW role (and drop the reverse call from bdrv_backing_detach()), so it
5
can be used for any child (with a proper role set).
5
6
6
It calls bdrv_get_full_backing_filename_from_filename() for now, but
7
Because so far no child has a proper role set, we need a temporary new
7
that will be changed in a follow-up patch.
8
callback for child_backing.detach that ensures bdrv_backing_detach() is
9
called for all COW children that do not have their role set yet.
10
11
(Also, move bdrv_child_cb_detach() down to group it with
12
bdrv_inherited_options() and bdrv_child_cb_attach().)
8
13
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Message-Id: <20200513110544.176672-14-mreitz@redhat.com>
11
Message-id: 20190201192935.18394-13-mreitz@redhat.com
16
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
18
---
14
block.c | 27 ++++++++++++++++++++-------
19
block.c | 27 ++++++++++++++++++++-------
15
1 file changed, 20 insertions(+), 7 deletions(-)
20
1 file changed, 20 insertions(+), 7 deletions(-)
16
21
17
diff --git a/block.c b/block.c
22
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
24
--- a/block.c
20
+++ b/block.c
25
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
26
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
22
}
27
int *child_flags, QDict *child_options,
28
int parent_flags, QDict *parent_options);
29
static void bdrv_child_cb_attach(BdrvChild *child);
30
+static void bdrv_child_cb_detach(BdrvChild *child);
31
32
/* If non-zero, use only whitelisted block drivers */
33
static int use_bdrv_whitelist;
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_drained_end(BdrvChild *child,
35
bdrv_drained_end_no_poll(bs, drained_end_counter);
23
}
36
}
24
37
25
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
38
-static void bdrv_child_cb_detach(BdrvChild *child)
26
+/*
39
-{
27
+ * If @filename is empty or NULL, this function returns NULL without
40
- BlockDriverState *bs = child->opaque;
28
+ * setting @errp. In all other cases, NULL will only be returned with
41
- bdrv_unapply_subtree_drain(child, bs);
29
+ * @errp set.
42
-}
30
+ */
43
-
31
+static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
44
static int bdrv_child_cb_inactivate(BdrvChild *child)
32
+ const char *filename, Error **errp)
33
{
45
{
34
- char *backed;
46
BlockDriverState *bs = child->opaque;
35
+ char *bs_filename;
47
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
36
48
bdrv_op_unblock_all(c->bs, parent->backing_blocker);
37
- bdrv_refresh_filename(bs);
49
error_free(parent->backing_blocker);
38
+ bdrv_refresh_filename(relative_to);
50
parent->backing_blocker = NULL;
51
+}
52
53
+/* XXX: Will be removed along with child_backing */
54
+static void bdrv_child_cb_detach_backing(BdrvChild *c)
55
+{
56
+ if (!(c->role & BDRV_CHILD_COW)) {
57
+ bdrv_backing_detach(c);
58
+ }
59
bdrv_child_cb_detach(c);
60
}
61
62
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_backing = {
63
.parent_is_bds = true,
64
.get_parent_desc = bdrv_child_get_parent_desc,
65
.attach = bdrv_child_cb_attach_backing,
66
- .detach = bdrv_backing_detach,
67
+ .detach = bdrv_child_cb_detach_backing,
68
.inherit_options = bdrv_backing_options,
69
.drained_begin = bdrv_child_cb_drained_begin,
70
.drained_poll = bdrv_child_cb_drained_poll,
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
72
bdrv_apply_subtree_drain(child, bs);
73
}
74
75
+static void bdrv_child_cb_detach(BdrvChild *child)
76
+{
77
+ BlockDriverState *bs = child->opaque;
39
+
78
+
40
+ bs_filename = relative_to->exact_filename[0]
79
+ if (child->role & BDRV_CHILD_COW) {
41
+ ? relative_to->exact_filename
80
+ bdrv_backing_detach(child);
42
+ : relative_to->filename;
81
+ }
43
82
+
44
- backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
83
+ bdrv_unapply_subtree_drain(child, bs);
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
+}
84
+}
51
+
85
+
52
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
86
static int bdrv_open_flags(BlockDriverState *bs, int flags)
53
+{
87
{
54
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
88
int open_flags = flags;
55
}
56
57
void bdrv_register(BlockDriver *bdrv)
58
--
89
--
59
2.20.1
90
2.25.4
60
91
61
92
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
While the basic idea is obvious and could be handled by the default
3
Any current user of child_file, child_format, and child_backing can and
4
bdrv_dirname() implementation, we cannot generate a directory name if
4
should use this generic BdrvChildClass instead, as it can handle all of
5
the gid or uid are set, so we have to explicitly return NULL in those
5
these cases. However, to be able to do so, the users must pass the
6
cases.
6
appropriate BdrvChildRole when the child is created/attached. (The
7
following commits will take care of that.)
7
8
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200513110544.176672-15-mreitz@redhat.com>
10
Message-id: 20190201192935.18394-19-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
---
13
block/nfs.c | 15 +++++++++++++++
14
include/block/block_int.h | 1 +
14
1 file changed, 15 insertions(+)
15
block.c | 24 ++++++++++++++++++++++++
16
2 files changed, 25 insertions(+)
15
17
16
diff --git a/block/nfs.c b/block/nfs.c
18
diff --git a/include/block/block_int.h b/include/block/block_int.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nfs.c
20
--- a/include/block/block_int.h
19
+++ b/block/nfs.c
21
+++ b/include/block/block_int.h
20
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
22
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
21
bs->full_open_options = opts;
23
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
24
};
25
26
+extern const BdrvChildClass child_of_bds;
27
extern const BdrvChildClass child_file;
28
extern const BdrvChildClass child_format;
29
extern const BdrvChildClass child_backing;
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
35
bdrv_unapply_subtree_drain(child, bs);
22
}
36
}
23
37
24
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
38
+static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
39
+ const char *filename, Error **errp)
25
+{
40
+{
26
+ NFSClient *client = bs->opaque;
41
+ if (c->role & BDRV_CHILD_COW) {
27
+
42
+ return bdrv_backing_update_filename(c, base, filename, errp);
28
+ if (client->uid || client->gid) {
29
+ bdrv_refresh_filename(bs);
30
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
31
+ bs->filename);
32
+ return NULL;
33
+ }
43
+ }
34
+
44
+ return 0;
35
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
36
+}
45
+}
37
+
46
+
38
#ifdef LIBNFS_FEATURE_PAGECACHE
47
+const BdrvChildClass child_of_bds = {
39
static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
48
+ .parent_is_bds = true,
40
Error **errp)
49
+ .get_parent_desc = bdrv_child_get_parent_desc,
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
50
+ .inherit_options = bdrv_inherited_options,
42
.bdrv_detach_aio_context = nfs_detach_aio_context,
51
+ .drained_begin = bdrv_child_cb_drained_begin,
43
.bdrv_attach_aio_context = nfs_attach_aio_context,
52
+ .drained_poll = bdrv_child_cb_drained_poll,
44
.bdrv_refresh_filename = nfs_refresh_filename,
53
+ .drained_end = bdrv_child_cb_drained_end,
45
+ .bdrv_dirname = nfs_dirname,
54
+ .attach = bdrv_child_cb_attach,
46
55
+ .detach = bdrv_child_cb_detach,
47
#ifdef LIBNFS_FEATURE_PAGECACHE
56
+ .inactivate = bdrv_child_cb_inactivate,
48
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
57
+ .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
58
+ .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
59
+ .update_filename = bdrv_child_cb_update_filename,
60
+};
61
+
62
static int bdrv_open_flags(BlockDriverState *bs, int flags)
63
{
64
int open_flags = flags;
49
--
65
--
50
2.20.1
66
2.25.4
51
67
52
68
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
bdrv_get_full_backing_filename_from_filename() breaks down when it comes
3
bdrv_format_default_perms() has one code path for backing files, and one
4
to JSON filenames. Using bdrv_dirname() as the basis is better because
4
for storage files. We want to pull them out into their own functions,
5
since we have BDS, we can descend through the BDS tree to the protocol
5
so make sure they are completely distinct before so the next patches
6
layer, which gives us a greater probability of finding a non-JSON name;
6
will be a bit cleaner.
7
also, bdrv_dirname() is more correct as it allows block drivers to
8
override the generation of that directory name in a protocol-specific
9
way.
10
11
We still need to keep bdrv_get_full_backing_filename_from_filename(),
12
though, because it has valid callers which need it during image creation
13
when no BDS is available yet.
14
15
This makes a test case in qemu-iotest 110, which was supposed to fail,
16
work. That is actually good, but we need to change the reference output
17
(and the comment in 110) accordingly.
18
7
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Message-id: 20190201192935.18394-20-mreitz@redhat.com
10
Message-Id: <20200513110544.176672-16-mreitz@redhat.com>
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
12
---
24
block.c | 20 +++++++++++++-------
13
block.c | 19 +++++++++++++------
25
tests/qemu-iotests/110 | 3 ++-
14
1 file changed, 13 insertions(+), 6 deletions(-)
26
tests/qemu-iotests/110.out | 2 +-
27
3 files changed, 16 insertions(+), 9 deletions(-)
28
15
29
diff --git a/block.c b/block.c
16
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
18
--- a/block.c
32
+++ b/block.c
19
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
20
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
34
static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
21
perm |= BLK_PERM_CONSISTENT_READ;
35
const char *filename, Error **errp)
22
}
36
{
23
shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
37
- char *bs_filename;
24
+
38
+ char *dir, *full_name;
25
+ if (bs->open_flags & BDRV_O_INACTIVE) {
39
26
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
40
- bdrv_refresh_filename(relative_to);
27
+ }
41
+ if (!filename || filename[0] == '\0') {
28
+
42
+ return NULL;
29
+ *nperm = perm;
43
+ } else if (path_has_protocol(filename) || path_is_absolute(filename)) {
30
+ *nshared = shared;
44
+ return g_strdup(filename);
31
} else {
32
/* We want consistent read from backing files if the parent needs it.
33
* No other operations are performed on backing files. */
34
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
35
36
shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
37
BLK_PERM_WRITE_UNCHANGED;
38
- }
39
40
- if (bs->open_flags & BDRV_O_INACTIVE) {
41
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
42
- }
43
+ if (bs->open_flags & BDRV_O_INACTIVE) {
44
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
45
+ }
46
47
- *nperm = perm;
48
- *nshared = shared;
49
+ *nperm = perm;
50
+ *nshared = shared;
45
+ }
51
+ }
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
}
52
}
61
53
62
char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
54
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
63
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
64
index XXXXXXX..XXXXXXX 100755
65
--- a/tests/qemu-iotests/110
66
+++ b/tests/qemu-iotests/110
67
@@ -XXX,XX +XXX,XX @@ echo '=== Non-reconstructable filename ==='
68
echo
69
70
# Across blkdebug without a config file, you cannot reconstruct filenames, so
71
-# qemu is incapable of knowing the directory of the top image
72
+# qemu is incapable of knowing the directory of the top image from the filename
73
+# alone. However, using bdrv_dirname(), it should still work.
74
TEST_IMG="json:{
75
'driver': '$IMGFMT',
76
'file': {
77
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/110.out
80
+++ b/tests/qemu-iotests/110.out
81
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
82
image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
83
file format: IMGFMT
84
virtual size: 64M (67108864 bytes)
85
-backing file: t.IMGFMT.base (cannot determine actual path)
86
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
87
88
=== Backing name is always relative to the backed image ===
89
90
--
55
--
91
2.20.1
56
2.25.4
92
57
93
58
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
When BDSs are created by qemu itself (e.g. as filters in block jobs),
3
Right now, bdrv_format_default_perms() is used by format parents
4
they may not have a "driver" option in their options QDict. When
4
(generally). We want to switch to a model where most parents use a
5
generating a json:{} filename, however, it must always be present.
5
single BdrvChildClass, which then decides the permissions based on the
6
child role. To do so, we have to split bdrv_format_default_perms() into
7
separate functions for each such role.
6
8
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200513110544.176672-17-mreitz@redhat.com>
9
Message-id: 20190201192935.18394-31-mreitz@redhat.com
11
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
13
---
12
block.c | 6 ++++++
14
block.c | 62 +++++++++++++++++++++++++++++++++++++--------------------
13
1 file changed, 6 insertions(+)
15
1 file changed, 40 insertions(+), 22 deletions(-)
14
16
15
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
19
--- a/block.c
18
+++ b/block.c
20
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
21
@@ -XXX,XX +XXX,XX @@ void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
20
}
22
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
21
}
23
}
22
24
23
+ if (!qdict_haskey(d, "driver")) {
25
+static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
24
+ /* Drivers created with bdrv_new_open_driver() may not have a
26
+ const BdrvChildClass *child_class,
25
+ * @driver option. Add it here. */
27
+ BdrvChildRole role,
26
+ qdict_put_str(d, "driver", bs->drv->format_name);
28
+ BlockReopenQueue *reopen_queue,
29
+ uint64_t perm, uint64_t shared,
30
+ uint64_t *nperm, uint64_t *nshared)
31
+{
32
+ assert(child_class == &child_backing ||
33
+ (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
34
+
35
+ /*
36
+ * We want consistent read from backing files if the parent needs it.
37
+ * No other operations are performed on backing files.
38
+ */
39
+ perm &= BLK_PERM_CONSISTENT_READ;
40
+
41
+ /*
42
+ * If the parent can deal with changing data, we're okay with a
43
+ * writable and resizable backing file.
44
+ * TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too?
45
+ */
46
+ if (shared & BLK_PERM_WRITE) {
47
+ shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
48
+ } else {
49
+ shared = 0;
27
+ }
50
+ }
28
+
51
+
29
return found_any;
52
+ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
53
+ BLK_PERM_WRITE_UNCHANGED;
54
+
55
+ if (bs->open_flags & BDRV_O_INACTIVE) {
56
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
57
+ }
58
+
59
+ *nperm = perm;
60
+ *nshared = shared;
61
+}
62
+
63
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
64
const BdrvChildClass *child_class,
65
BdrvChildRole role,
66
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
67
*nperm = perm;
68
*nshared = shared;
69
} else {
70
- /* We want consistent read from backing files if the parent needs it.
71
- * No other operations are performed on backing files. */
72
- perm &= BLK_PERM_CONSISTENT_READ;
73
-
74
- /* If the parent can deal with changing data, we're okay with a
75
- * writable and resizable backing file. */
76
- /* TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too? */
77
- if (shared & BLK_PERM_WRITE) {
78
- shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
79
- } else {
80
- shared = 0;
81
- }
82
-
83
- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
84
- BLK_PERM_WRITE_UNCHANGED;
85
-
86
- if (bs->open_flags & BDRV_O_INACTIVE) {
87
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
88
- }
89
-
90
- *nperm = perm;
91
- *nshared = shared;
92
+ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
93
+ perm, shared, nperm, nshared);
94
}
30
}
95
}
31
96
32
--
97
--
33
2.20.1
98
2.25.4
34
99
35
100
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Instead of having every block driver which implements
3
Right now, bdrv_format_default_perms() is used by format parents
4
bdrv_refresh_filename() copy all of the strong runtime options over to
4
(generally). We want to switch to a model where most parents use a
5
bs->full_open_options, implement this process generically in
5
single BdrvChildClass, which then decides the permissions based on the
6
bdrv_refresh_filename().
6
child role. To do so, we have to split bdrv_format_default_perms() into
7
separate functions for each such role.
7
8
8
This patch only adds this new generic implementation, it does not remove
9
Note that bdrv_default_perms_for_storage() currently handles all DATA |
9
the old functionality. This is done in a follow-up patch.
10
METADATA children. A follow-up patch is going to split it further into
10
11
one function for each case.
11
With this patch, some superfluous information (that should never have
12
been there) may be removed from some JSON filenames, as can be seen in
13
the change to iotests 110's and 228's reference outputs.
14
12
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-id: 20190201192935.18394-24-mreitz@redhat.com
14
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20200513110544.176672-18-mreitz@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
17
---
19
block.c | 116 ++++++++++++++++++++++++++++++++++++-
18
block.c | 71 +++++++++++++++++++++++++++++++++++++--------------------
20
tests/qemu-iotests/110.out | 2 +-
19
1 file changed, 46 insertions(+), 25 deletions(-)
21
tests/qemu-iotests/228 | 7 ++-
22
tests/qemu-iotests/228.out | 2 +-
23
4 files changed, 121 insertions(+), 6 deletions(-)
24
20
25
diff --git a/block.c b/block.c
21
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
23
--- a/block.c
28
+++ b/block.c
24
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ out:
25
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
30
return to_replace_bs;
26
*nshared = shared;
31
}
27
}
32
28
33
+/**
29
+static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
34
+ * Iterates through the list of runtime option keys that are said to
30
+ const BdrvChildClass *child_class,
35
+ * be "strong" for a BDS. An option is called "strong" if it changes
31
+ BdrvChildRole role,
36
+ * a BDS's data. For example, the null block driver's "size" and
32
+ BlockReopenQueue *reopen_queue,
37
+ * "read-zeroes" options are strong, but its "latency-ns" option is
33
+ uint64_t perm, uint64_t shared,
38
+ * not.
34
+ uint64_t *nperm, uint64_t *nshared)
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
+{
35
+{
46
+ static const char *const global_options[] = {
36
+ int flags;
47
+ "driver", "filename", NULL
48
+ };
49
+
37
+
50
+ if (!curopt) {
38
+ assert(child_class == &child_file ||
51
+ return &global_options[0];
39
+ (child_class == &child_of_bds &&
40
+ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))));
41
+
42
+ flags = bdrv_reopen_get_flags(reopen_queue, bs);
43
+
44
+ /*
45
+ * Apart from the modifications below, the same permissions are
46
+ * forwarded and left alone as for filters
47
+ */
48
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
49
+ perm, shared, &perm, &shared);
50
+
51
+ /* Format drivers may touch metadata even if the guest doesn't write */
52
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
53
+ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
52
+ }
54
+ }
53
+
55
+
54
+ curopt++;
56
+ /*
55
+ if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) {
57
+ * bs->file always needs to be consistent because of the metadata. We
56
+ curopt = bs->drv->strong_runtime_opts;
58
+ * can never allow other users to resize or write to it.
59
+ */
60
+ if (!(flags & BDRV_O_NO_IO)) {
61
+ perm |= BLK_PERM_CONSISTENT_READ;
62
+ }
63
+ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
64
+
65
+ if (bs->open_flags & BDRV_O_INACTIVE) {
66
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
57
+ }
67
+ }
58
+
68
+
59
+ return (curopt && *curopt) ? curopt : NULL;
69
+ *nperm = perm;
70
+ *nshared = shared;
60
+}
71
+}
61
+
72
+
62
+/**
73
void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
63
+ * Copies all strong runtime options from bs->options to the given
74
const BdrvChildClass *child_class,
64
+ * QDict. The set of strong option keys is determined by invoking
75
BdrvChildRole role,
65
+ * strong_options().
76
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
66
+ *
77
assert(child_class == &child_backing || child_class == &child_file);
67
+ * Returns true iff any strong option was present in bs->options (and
78
68
+ * thus copied to the target QDict) with the exception of "filename"
79
if (!backing) {
69
+ * and "driver". The caller is expected to use this value to decide
80
- int flags = bdrv_reopen_get_flags(reopen_queue, bs);
70
+ * whether the existence of strong options prevents the generation of
81
-
71
+ * a plain filename.
82
- /* Apart from the modifications below, the same permissions are
72
+ */
83
- * forwarded and left alone as for filters */
73
+static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
84
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
74
+{
85
- perm, shared, &perm, &shared);
75
+ bool found_any = false;
86
-
76
+ const char *const *option_name = NULL;
87
- /* Format drivers may touch metadata even if the guest doesn't write */
77
+
88
- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
78
+ if (!bs->drv) {
89
- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
79
+ return false;
90
- }
80
+ }
91
-
81
+
92
- /* bs->file always needs to be consistent because of the metadata. We
82
+ while ((option_name = strong_options(bs, option_name))) {
93
- * can never allow other users to resize or write to it. */
83
+ bool option_given = false;
94
- if (!(flags & BDRV_O_NO_IO)) {
84
+
95
- perm |= BLK_PERM_CONSISTENT_READ;
85
+ assert(strlen(*option_name) > 0);
96
- }
86
+ if ((*option_name)[strlen(*option_name) - 1] != '.') {
97
- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
87
+ QObject *entry = qdict_get(bs->options, *option_name);
98
-
88
+ if (!entry) {
99
- if (bs->open_flags & BDRV_O_INACTIVE) {
89
+ continue;
100
- shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
90
+ }
101
- }
91
+
102
-
92
+ qdict_put_obj(d, *option_name, qobject_ref(entry));
103
- *nperm = perm;
93
+ option_given = true;
104
- *nshared = shared;
94
+ } else {
105
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
95
+ const QDictEntry *entry;
106
+ perm, shared, nperm, nshared);
96
+ for (entry = qdict_first(bs->options); entry;
107
} else {
97
+ entry = qdict_next(bs->options, entry))
108
bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
98
+ {
109
perm, shared, nperm, nshared);
99
+ if (strstart(qdict_entry_key(entry), *option_name, NULL)) {
100
+ qdict_put_obj(d, qdict_entry_key(entry),
101
+ qobject_ref(qdict_entry_value(entry)));
102
+ option_given = true;
103
+ }
104
+ }
105
+ }
106
+
107
+ /* While "driver" and "filename" need to be included in a JSON filename,
108
+ * their existence does not prohibit generation of a plain filename. */
109
+ if (!found_any && option_given &&
110
+ strcmp(*option_name, "driver") && strcmp(*option_name, "filename"))
111
+ {
112
+ found_any = true;
113
+ }
114
+ }
115
+
116
+ return found_any;
117
+}
118
+
119
static bool append_open_options(QDict *d, BlockDriverState *bs)
120
{
121
const QDictEntry *entry;
122
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
123
bs->full_open_options = opts;
124
}
125
126
+ /* Gather the options QDict */
127
+ opts = qdict_new();
128
+ append_strong_runtime_options(opts, bs);
129
+
130
+ if (drv->bdrv_gather_child_options) {
131
+ /* Some block drivers may not want to present all of their children's
132
+ * options, or name them differently from BdrvChild.name */
133
+ drv->bdrv_gather_child_options(bs, opts, backing_overridden);
134
+ } else {
135
+ QLIST_FOREACH(child, &bs->children, next) {
136
+ if (child->role == &child_backing && !backing_overridden) {
137
+ /* We can skip the backing BDS if it has not been overridden */
138
+ continue;
139
+ }
140
+
141
+ qdict_put(opts, child->name,
142
+ qobject_ref(child->bs->full_open_options));
143
+ }
144
+
145
+ if (backing_overridden && !bs->backing) {
146
+ /* Force no backing file */
147
+ qdict_put_null(opts, "backing");
148
+ }
149
+ }
150
+
151
+ qobject_unref(bs->full_open_options);
152
+ bs->full_open_options = opts;
153
+
154
if (bs->exact_filename[0]) {
155
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
156
- } else if (bs->full_open_options) {
157
+ } else {
158
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
159
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
160
qstring_get_str(json));
161
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
162
index XXXXXXX..XXXXXXX 100644
163
--- a/tests/qemu-iotests/110.out
164
+++ b/tests/qemu-iotests/110.out
165
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
166
167
=== Nodes without a common directory ===
168
169
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "blkverify": false, "rewrite-corrupted": false, "vote-threshold": 1}}
170
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
171
file format: IMGFMT
172
virtual size: 64M (67108864 bytes)
173
backing file: t.IMGFMT.base (cannot determine actual path)
174
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
175
index XXXXXXX..XXXXXXX 100755
176
--- a/tests/qemu-iotests/228
177
+++ b/tests/qemu-iotests/228
178
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
179
overlay='node0')
180
181
# This should give us the original plain result
182
- # FIXME: Currently, the block layer considers the runtime backing
183
- # file to be different from the image header, which is
184
- # wrong. This is fixed by a future patch.
185
+ # FIXME: Currently, it yields a json:{} filename even though it
186
+ # only contains a @driver and a @file entry, so a plain
187
+ # filename would obviously suffice. This is fixed by a
188
+ # future patch.
189
190
log_node_info(vm.node_info('node0'))
191
192
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
193
index XXXXXXX..XXXXXXX 100644
194
--- a/tests/qemu-iotests/228.out
195
+++ b/tests/qemu-iotests/228.out
196
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
197
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
198
{"return": {}}
199
200
-bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
201
+bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
202
bs->backing_file: TEST_DIR/PID-base.img
203
bs->backing->bs->filename: TEST_DIR/PID-base.img
204
205
--
110
--
206
2.20.1
111
2.25.4
207
112
208
113
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
bdrv_refresh_filename() should simply skip all implicit nodes. They are
3
We can be less restrictive about pure data children than those with
4
supposed to be invisible to the user, so they should not appear in
4
metadata on them, so let bdrv_default_perms_for_storage() handle
5
filename information.
5
metadata children differently from pure data children.
6
7
As explained in the code, the restrictions on metadata children are
8
strictly stricter than those for pure data children, so in theory we
9
just have to distinguish between pure-data and all other storage
10
children (pure metadata or data+metadata). In practice, that is not
11
obvious, though, so we have two independent code paths for metadata and
12
for data children, and data+metadata children will go through both
13
(without the path for data children doing anything meaningful).
6
14
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-Id: <20200513110544.176672-19-mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-id: 20190201192935.18394-4-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
19
---
13
block.c | 14 ++++++++++++++
20
block.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++----------
14
1 file changed, 14 insertions(+)
21
1 file changed, 48 insertions(+), 10 deletions(-)
15
22
16
diff --git a/block.c b/block.c
23
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
25
--- a/block.c
19
+++ b/block.c
26
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
21
bdrv_refresh_filename(child->bs);
28
bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
29
perm, shared, &perm, &shared);
30
31
- /* Format drivers may touch metadata even if the guest doesn't write */
32
- if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
33
- perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
34
+ if (role & BDRV_CHILD_METADATA) {
35
+ /* Format drivers may touch metadata even if the guest doesn't write */
36
+ if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
37
+ perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
38
+ }
39
+
40
+ /*
41
+ * bs->file always needs to be consistent because of the
42
+ * metadata. We can never allow other users to resize or write
43
+ * to it.
44
+ */
45
+ if (!(flags & BDRV_O_NO_IO)) {
46
+ perm |= BLK_PERM_CONSISTENT_READ;
47
+ }
48
+ shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
22
}
49
}
23
50
24
+ if (bs->implicit) {
51
- /*
25
+ /* For implicit nodes, just copy everything from the single child */
52
- * bs->file always needs to be consistent because of the metadata. We
26
+ child = QLIST_FIRST(&bs->children);
53
- * can never allow other users to resize or write to it.
27
+ assert(QLIST_NEXT(child, next) == NULL);
54
- */
55
- if (!(flags & BDRV_O_NO_IO)) {
56
- perm |= BLK_PERM_CONSISTENT_READ;
57
+ if (role & BDRV_CHILD_DATA) {
58
+ /*
59
+ * Technically, everything in this block is a subset of the
60
+ * BDRV_CHILD_METADATA path taken above, and so this could
61
+ * be an "else if" branch. However, that is not obvious, and
62
+ * this function is not performance critical, therefore we let
63
+ * this be an independent "if".
64
+ */
28
+
65
+
29
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
66
+ /*
30
+ child->bs->exact_filename);
67
+ * We cannot allow other users to resize the file because the
31
+ pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
68
+ * format driver might have some assumptions about the size
69
+ * (e.g. because it is stored in metadata, or because the file
70
+ * is split into fixed-size data files).
71
+ */
72
+ shared &= ~BLK_PERM_RESIZE;
32
+
73
+
33
+ bs->full_open_options = qobject_ref(child->bs->full_open_options);
74
+ /*
75
+ * WRITE_UNCHANGED often cannot be performed as such on the
76
+ * data file. For example, the qcow2 driver may still need to
77
+ * write copied clusters on copy-on-read.
78
+ */
79
+ if (perm & BLK_PERM_WRITE_UNCHANGED) {
80
+ perm |= BLK_PERM_WRITE;
81
+ }
34
+
82
+
35
+ return;
83
+ /*
36
+ }
84
+ * If the data file is written to, the format driver may
37
+
85
+ * expect to be able to resize it by writing beyond the EOF.
38
if (drv->bdrv_refresh_filename) {
86
+ */
39
/* Obsolete information is of no use here, so drop the old file name
87
+ if (perm & BLK_PERM_WRITE) {
40
* information before refreshing it */
88
+ perm |= BLK_PERM_RESIZE;
89
+ }
90
}
91
- shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
92
93
if (bs->open_flags & BDRV_O_INACTIVE) {
94
shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
41
--
95
--
42
2.20.1
96
2.25.4
43
97
44
98
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This function may be implemented by block drivers to derive a directory
3
This callback can be used by BDSs that use child_of_bds with the
4
name from a BDS. Concatenating this g_free()-able string with a relative
4
appropriate BdrvChildRole for their children.
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
5
9
If a BDS's driver does not implement this function, bdrv_dirname() will
6
Also, make bdrv_format_default_perms() use it for child_of_bds children
10
fall through to the BDS's file if it exists. If it does not, the
7
(just a temporary solution until we can drop bdrv_format_default_perms()
11
exact_filename field will be used to generate a directory name.
8
altogether).
12
9
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-Id: <20200513110544.176672-20-mreitz@redhat.com>
15
Message-id: 20190201192935.18394-15-mreitz@redhat.com
12
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
14
---
18
include/block/block.h | 1 +
15
include/block/block_int.h | 11 +++++++++++
19
include/block/block_int.h | 7 +++++++
16
block.c | 32 ++++++++++++++++++++++++++++++++
20
block.c | 27 +++++++++++++++++++++++++++
17
2 files changed, 43 insertions(+)
21
3 files changed, 35 insertions(+)
22
18
23
diff --git a/include/block/block.h b/include/block/block.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/block/block.h
26
+++ b/include/block/block.h
27
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
28
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
29
const char *backing,
30
Error **errp);
31
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
32
33
int path_has_protocol(const char *path);
34
int path_is_absolute(const char *path);
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
19
diff --git a/include/block/block_int.h b/include/block/block_int.h
36
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int.h
21
--- a/include/block/block_int.h
38
+++ b/include/block/block_int.h
22
+++ b/include/block/block_int.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
23
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
40
24
bool bdrv_recurse_can_replace(BlockDriverState *bs,
41
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
25
BlockDriverState *to_replace);
42
26
43
+ /*
27
+/*
44
+ * Returns an allocated string which is the directory name of this BDS: It
28
+ * Default implementation for BlockDriver.bdrv_child_perm() that can
45
+ * will be used to make relative filenames absolute by prepending this
29
+ * be used by block filters and image formats, as long as they use the
46
+ * function's return value to them.
30
+ * child_of_bds child class and set an appropriate BdrvChildRole.
47
+ */
31
+ */
48
+ char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
32
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
33
+ const BdrvChildClass *child_class, BdrvChildRole role,
34
+ BlockReopenQueue *reopen_queue,
35
+ uint64_t perm, uint64_t shared,
36
+ uint64_t *nperm, uint64_t *nshared);
49
+
37
+
50
/* aio */
38
/*
51
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
39
* Default implementation for drivers to pass bdrv_co_block_status() to
52
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
40
* their file.
53
diff --git a/block.c b/block.c
41
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
43
--- a/block.c
56
+++ b/block.c
44
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
45
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
46
uint64_t *nperm, uint64_t *nshared)
47
{
48
bool backing = (child_class == &child_backing);
49
+
50
+ if (child_class == &child_of_bds) {
51
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
52
+ perm, shared, nperm, nshared);
53
+ return;
54
+ }
55
+
56
assert(child_class == &child_backing || child_class == &child_file);
57
58
if (!backing) {
59
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
58
}
60
}
59
}
61
}
60
62
61
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
63
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
64
+ const BdrvChildClass *child_class, BdrvChildRole role,
65
+ BlockReopenQueue *reopen_queue,
66
+ uint64_t perm, uint64_t shared,
67
+ uint64_t *nperm, uint64_t *nshared)
62
+{
68
+{
63
+ BlockDriver *drv = bs->drv;
69
+ assert(child_class == &child_of_bds);
64
+
70
+
65
+ if (!drv) {
71
+ if (role & BDRV_CHILD_FILTERED) {
66
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
72
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
67
+ return NULL;
73
+ BDRV_CHILD_COW)));
74
+ bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
75
+ perm, shared, nperm, nshared);
76
+ } else if (role & BDRV_CHILD_COW) {
77
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
78
+ bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
79
+ perm, shared, nperm, nshared);
80
+ } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
81
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
82
+ perm, shared, nperm, nshared);
83
+ } else {
84
+ g_assert_not_reached();
68
+ }
85
+ }
69
+
70
+ if (drv->bdrv_dirname) {
71
+ return drv->bdrv_dirname(bs, errp);
72
+ }
73
+
74
+ if (bs->file) {
75
+ return bdrv_dirname(bs->file->bs, errp);
76
+ }
77
+
78
+ bdrv_refresh_filename(bs);
79
+ if (bs->exact_filename[0] != '\0') {
80
+ return path_combine(bs->exact_filename, "");
81
+ }
82
+
83
+ error_setg(errp, "Cannot generate a base directory for %s nodes",
84
+ drv->format_name);
85
+ return NULL;
86
+}
86
+}
87
+
87
+
88
/*
88
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
89
* Hot add/remove a BDS's child. So the user can take a child offline when
89
{
90
* it is broken and take a new child online
90
static const uint64_t permissions[] = {
91
--
91
--
92
2.20.1
92
2.25.4
93
93
94
94
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Both of the defaults we currently have in the curl driver are named
3
Split raw_read_options() into one function that actually just reads the
4
based on a slightly different schema, let's unify that and call both
4
options, and another that applies them. This will allow us to detect
5
CURL_BLOCK_OPT_${NAME}_DEFAULT.
5
whether the user has specified any options before attaching the file
6
6
child (so we can decide on its role based on the options).
7
While at it, we can add a macro for the third option for which a default
8
exists, namely "sslverify".
9
7
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Message-id: 20190201192935.18394-28-mreitz@redhat.com
10
Message-Id: <20200513110544.176672-21-mreitz@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
12
---
15
block/curl.c | 13 ++++++++-----
13
block/raw-format.c | 110 ++++++++++++++++++++++++++-------------------
16
1 file changed, 8 insertions(+), 5 deletions(-)
14
1 file changed, 65 insertions(+), 45 deletions(-)
17
15
18
diff --git a/block/curl.c b/block/curl.c
16
diff --git a/block/raw-format.c b/block/raw-format.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/block/curl.c
18
--- a/block/raw-format.c
21
+++ b/block/curl.c
19
+++ b/block/raw-format.c
22
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
20
@@ -XXX,XX +XXX,XX @@ static QemuOptsList raw_create_opts = {
23
21
}
24
#define CURL_NUM_STATES 8
22
};
25
#define CURL_NUM_ACB 8
23
26
-#define READ_AHEAD_DEFAULT (256 * 1024)
24
-static int raw_read_options(QDict *options, BlockDriverState *bs,
27
-#define CURL_TIMEOUT_DEFAULT 5
25
- BDRVRawState *s, Error **errp)
28
#define CURL_TIMEOUT_MAX 10000
26
+static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
29
27
+ uint64_t *size, Error **errp)
30
#define CURL_BLOCK_OPT_URL "url"
28
{
31
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
29
Error *local_err = NULL;
32
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
30
QemuOpts *opts = NULL;
33
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
31
- int64_t real_size = 0;
34
32
int ret;
35
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
33
36
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
34
- real_size = bdrv_getlength(bs->file->bs);
37
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
35
- if (real_size < 0) {
36
- error_setg_errno(errp, -real_size, "Could not get image size");
37
- return real_size;
38
- }
39
-
40
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
41
qemu_opts_absorb_qdict(opts, options, &local_err);
42
if (local_err) {
43
@@ -XXX,XX +XXX,XX @@ static int raw_read_options(QDict *options, BlockDriverState *bs,
44
goto end;
45
}
46
47
- s->offset = qemu_opt_get_size(opts, "offset", 0);
48
- if (s->offset > real_size) {
49
- error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
50
- "size of the containing file (%" PRId64 ")",
51
- s->offset, real_size);
52
- ret = -EINVAL;
53
- goto end;
54
- }
55
+ *offset = qemu_opt_get_size(opts, "offset", 0);
56
+ *has_size = qemu_opt_find(opts, "size");
57
+ *size = qemu_opt_get_size(opts, "size", 0);
58
59
- if (qemu_opt_find(opts, "size") != NULL) {
60
- s->size = qemu_opt_get_size(opts, "size", 0);
61
- s->has_size = true;
62
- } else {
63
- s->has_size = false;
64
- s->size = real_size - s->offset;
65
+ ret = 0;
66
+end:
67
+ qemu_opts_del(opts);
68
+ return ret;
69
+}
38
+
70
+
39
struct BDRVCURLState;
71
+static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
40
72
+ uint64_t offset, bool has_size, uint64_t size,
41
static bool libcurl_initialized;
73
+ Error **errp)
42
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
74
+{
75
+ int64_t real_size = 0;
76
+
77
+ real_size = bdrv_getlength(bs->file->bs);
78
+ if (real_size < 0) {
79
+ error_setg_errno(errp, -real_size, "Could not get image size");
80
+ return real_size;
43
}
81
}
44
82
45
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
83
/* Check size and offset */
46
- READ_AHEAD_DEFAULT);
84
- if ((real_size - s->offset) < s->size) {
47
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
85
+ if (offset > real_size) {
48
if ((s->readahead_size & 0x1ff) != 0) {
86
+ error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
49
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
87
+ "size of the containing file (%" PRId64 ")",
50
s->readahead_size);
88
+ s->offset, real_size);
51
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
89
+ return -EINVAL;
90
+ }
91
+
92
+ if (has_size && (real_size - offset) < size) {
93
error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
94
- "(%" PRIu64 ") has to be smaller or equal to the "
95
- " actual size of the containing file (%" PRId64 ")",
96
- s->offset, s->size, real_size);
97
- ret = -EINVAL;
98
- goto end;
99
+ "(%" PRIu64 ") has to be smaller or equal to the "
100
+ " actual size of the containing file (%" PRId64 ")",
101
+ s->offset, s->size, real_size);
102
+ return -EINVAL;
52
}
103
}
53
104
54
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
105
/* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
55
- CURL_TIMEOUT_DEFAULT);
106
* up and leaking out of the specified area. */
56
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
107
- if (s->has_size && !QEMU_IS_ALIGNED(s->size, BDRV_SECTOR_SIZE)) {
57
if (s->timeout > CURL_TIMEOUT_MAX) {
108
+ if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
58
error_setg(errp, "timeout parameter is too large or negative");
109
error_setg(errp, "Specified size is not multiple of %llu",
59
goto out_noclean;
110
- BDRV_SECTOR_SIZE);
111
- ret = -EINVAL;
112
- goto end;
113
+ BDRV_SECTOR_SIZE);
114
+ return -EINVAL;
60
}
115
}
61
116
62
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
117
- ret = 0;
63
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
118
-
64
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
119
-end:
65
120
+ s->offset = offset;
66
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
121
+ s->has_size = has_size;
67
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
122
+ s->size = has_size ? size : real_size - offset;
123
124
- qemu_opts_del(opts);
125
-
126
- return ret;
127
+ return 0;
128
}
129
130
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
131
BlockReopenQueue *queue, Error **errp)
132
{
133
+ bool has_size;
134
+ uint64_t offset, size;
135
+ int ret;
136
+
137
assert(reopen_state != NULL);
138
assert(reopen_state->bs != NULL);
139
140
reopen_state->opaque = g_new0(BDRVRawState, 1);
141
142
- return raw_read_options(
143
- reopen_state->options,
144
- reopen_state->bs,
145
- reopen_state->opaque,
146
- errp);
147
+ ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
148
+ errp);
149
+ if (ret < 0) {
150
+ return ret;
151
+ }
152
+
153
+ ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
154
+ offset, has_size, size, errp);
155
+ if (ret < 0) {
156
+ return ret;
157
+ }
158
+
159
+ return 0;
160
}
161
162
static void raw_reopen_commit(BDRVReopenState *state)
163
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
164
Error **errp)
165
{
166
BDRVRawState *s = bs->opaque;
167
+ bool has_size;
168
+ uint64_t offset, size;
169
int ret;
170
171
+ ret = raw_read_options(options, &offset, &has_size, &size, errp);
172
+ if (ret < 0) {
173
+ return ret;
174
+ }
175
+
176
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
177
false, errp);
178
if (!bs->file) {
179
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
180
bs->file->bs->filename);
181
}
182
183
- ret = raw_read_options(options, bs, s, errp);
184
+ ret = raw_apply_options(bs, s, offset, has_size, size, errp);
185
if (ret < 0) {
186
return ret;
187
}
68
--
188
--
69
2.20.1
189
2.25.4
70
190
71
191
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
While the common implementation for bdrv_dirname() should return NULL
3
Both users (quorum and blkverify) use child_format for
4
for quorum BDSs already (because they do not have a file node and their
4
not-really-filtered children, so the appropriate BdrvChildRole in both
5
exact_filename field should be empty), there is no reason not to make
5
cases is DATA. (Note that this will cause bdrv_inherited_options() to
6
that explicit.
6
force-allow format probing.)
7
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20200513110544.176672-22-mreitz@redhat.com>
11
Message-id: 20190201192935.18394-17-mreitz@redhat.com
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
12
---
14
block/quorum.c | 11 +++++++++++
13
block/blkverify.c | 4 ++--
15
1 file changed, 11 insertions(+)
14
block/quorum.c | 6 ++++--
15
2 files changed, 6 insertions(+), 4 deletions(-)
16
16
17
diff --git a/block/blkverify.c b/block/blkverify.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
20
+++ b/block/blkverify.c
21
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
22
23
/* Open the test file */
24
s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
25
- "test", bs, &child_format, 0, false,
26
- &local_err);
27
+ "test", bs, &child_of_bds, BDRV_CHILD_DATA,
28
+ false, &local_err);
29
if (local_err) {
30
ret = -EINVAL;
31
error_propagate(errp, local_err);
17
diff --git a/block/quorum.c b/block/quorum.c
32
diff --git a/block/quorum.c b/block/quorum.c
18
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
34
--- a/block/quorum.c
20
+++ b/block/quorum.c
35
+++ b/block/quorum.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
36
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
22
bs->full_open_options = opts;
37
assert(ret < 32);
23
}
38
24
39
s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
25
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
40
- &child_format, 0, false, &local_err);
26
+{
41
+ &child_of_bds, BDRV_CHILD_DATA, false,
27
+ /* In general, there are multiple BDSs with different dirnames below this
42
+ &local_err);
28
+ * one; so there is no unique dirname we could return (unless all are equal
43
if (local_err) {
29
+ * by chance, or there is only one). Therefore, to be consistent, just
44
ret = -EINVAL;
30
+ * always return NULL. */
45
goto close_exit;
31
+ error_setg(errp, "Cannot generate a base directory for quorum nodes");
46
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
32
+ return NULL;
47
/* We can safely add the child now */
33
+}
48
bdrv_ref(child_bs);
34
+
49
35
static BlockDriver bdrv_quorum = {
50
- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, 0, errp);
36
.format_name = "quorum",
51
+ child = bdrv_attach_child(bs, child_bs, indexstr, &child_of_bds,
37
52
+ BDRV_CHILD_DATA, errp);
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
53
if (child == NULL) {
39
.bdrv_open = quorum_open,
54
s->next_child_index--;
40
.bdrv_close = quorum_close,
55
goto out;
41
.bdrv_refresh_filename = quorum_refresh_filename,
42
+ .bdrv_dirname = quorum_dirname,
43
44
.bdrv_co_flush_to_disk = quorum_co_flush,
45
46
--
56
--
47
2.20.1
57
2.25.4
48
58
49
59
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-9-mreitz@redhat.com
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Message-Id: <20200513110544.176672-23-mreitz@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
---
7
tests/qemu-iotests/228 | 242 +++++++++++++++++++++++++++++++++++++
8
include/block/block_int.h | 1 -
8
tests/qemu-iotests/228.out | 84 +++++++++++++
9
block.c | 29 -----------------------------
9
tests/qemu-iotests/group | 1 +
10
2 files changed, 30 deletions(-)
10
3 files changed, 327 insertions(+)
11
create mode 100755 tests/qemu-iotests/228
12
create mode 100644 tests/qemu-iotests/228.out
13
11
14
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
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
13
index XXXXXXX..XXXXXXX 100644
354
--- a/tests/qemu-iotests/group
14
--- a/include/block/block_int.h
355
+++ b/tests/qemu-iotests/group
15
+++ b/include/block/block_int.h
356
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
357
225 rw auto quick
17
358
226 auto quick
18
extern const BdrvChildClass child_of_bds;
359
227 auto quick
19
extern const BdrvChildClass child_file;
360
+228 rw auto quick
20
-extern const BdrvChildClass child_format;
361
229 auto quick
21
extern const BdrvChildClass child_backing;
362
231 auto quick
22
363
232 auto quick
23
struct BdrvChild {
24
diff --git a/block.c b/block.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
27
+++ b/block.c
28
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_file = {
29
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
30
};
31
32
-/*
33
- * Returns the options and flags that bs->file should get if the use of formats
34
- * (and not only protocols) is permitted for it, based on the given options and
35
- * flags for the parent BDS
36
- */
37
-static void bdrv_inherited_fmt_options(BdrvChildRole role,
38
- bool parent_is_format,
39
- int *child_flags, QDict *child_options,
40
- int parent_flags, QDict *parent_options)
41
-{
42
- bdrv_inherited_options(BDRV_CHILD_DATA, false,
43
- child_flags, child_options,
44
- parent_flags, parent_options);
45
-}
46
-
47
-const BdrvChildClass child_format = {
48
- .parent_is_bds = true,
49
- .get_parent_desc = bdrv_child_get_parent_desc,
50
- .inherit_options = bdrv_inherited_fmt_options,
51
- .drained_begin = bdrv_child_cb_drained_begin,
52
- .drained_poll = bdrv_child_cb_drained_poll,
53
- .drained_end = bdrv_child_cb_drained_end,
54
- .attach = bdrv_child_cb_attach,
55
- .detach = bdrv_child_cb_detach,
56
- .inactivate = bdrv_child_cb_inactivate,
57
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
58
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
59
-};
60
-
61
static void bdrv_backing_attach(BdrvChild *c)
62
{
63
BlockDriverState *parent = c->opaque;
364
--
64
--
365
2.20.1
65
2.25.4
366
66
367
67
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Basically, bdrv_refresh_filename() should respect all children of a
3
Make all parents of backing files pass the appropriate BdrvChildRole.
4
BlockDriverState. However, generally those children are driver-specific,
4
By doing so, we can switch their BdrvChildClass over to the generic
5
so this function cannot handle the general case. On the other hand,
5
child_of_bds, which will do the right thing when given a correct
6
there are only few drivers which use other children than @file and
6
BdrvChildRole.
7
@backing (that being vmdk, quorum, and blkverify).
8
9
Most block drivers only use @file and/or @backing (if they use any
10
children at all). Both can be implemented directly in
11
bdrv_refresh_filename.
12
13
The user overriding the file's filename is already handled, however, the
14
user overriding the backing file is not. If this is done, opening the
15
BDS with the plain filename of its file will not be correct, so we may
16
not set bs->exact_filename in that case.
17
18
iotest 051 contains test cases for overriding the backing file, and so
19
its output changes with this patch applied.
20
7
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20200513110544.176672-24-mreitz@redhat.com>
23
Message-id: 20190201192935.18394-6-mreitz@redhat.com
10
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
12
---
26
block.c | 38 ++++++++++++++++++++++++++++++++++-
13
block.c | 26 ++++++++++++++++++++------
27
tests/qemu-iotests/051.out | 8 ++++----
14
block/backup-top.c | 2 +-
28
tests/qemu-iotests/051.pc.out | 8 ++++----
15
block/vvfat.c | 3 ++-
29
3 files changed, 45 insertions(+), 9 deletions(-)
16
tests/test-bdrv-drain.c | 13 +++++++------
17
4 files changed, 30 insertions(+), 14 deletions(-)
30
18
31
diff --git a/block.c b/block.c
19
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
21
--- a/block.c
34
+++ b/block.c
22
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
23
@@ -XXX,XX +XXX,XX @@ static bool bdrv_inherits_from_recursive(BlockDriverState *child,
36
return found_any;
24
return child != NULL;
37
}
25
}
38
26
39
+/* Note: This function may return false positives; it may return true
27
+/*
40
+ * even if opening the backing file specified by bs's image header
28
+ * Return the BdrvChildRole for @bs's backing child. bs->backing is
41
+ * would result in exactly bs->backing. */
29
+ * mostly used for COW backing children (role = COW), but also for
42
+static bool bdrv_backing_overridden(BlockDriverState *bs)
30
+ * filtered children (role = FILTERED | PRIMARY).
31
+ */
32
+static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
43
+{
33
+{
44
+ if (bs->backing) {
34
+ if (bs->drv && bs->drv->is_filter) {
45
+ return strcmp(bs->auto_backing_file,
35
+ return BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
46
+ bs->backing->bs->filename);
47
+ } else {
36
+ } else {
48
+ /* No backing BDS, so if the image header reports any backing
37
+ return BDRV_CHILD_COW;
49
+ * file, it must have been suppressed */
50
+ return bs->auto_backing_file[0] != '\0';
51
+ }
38
+ }
52
+}
39
+}
53
+
40
+
54
/* Updates the following BDS fields:
41
/*
55
* - exact_filename: A filename which may be used for opening a block device
42
* Sets the backing file link of a BDS. A new reference is created; callers
56
* which (mostly) equals the given BDS (even without any
43
* which don't need their own reference any more must call bdrv_unref().
44
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
45
goto out;
46
}
47
48
- bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
49
- 0, errp);
50
+ bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds,
51
+ bdrv_backing_role(bs), errp);
52
/* If backing_hd was already part of bs's backing chain, and
53
* inherits_from pointed recursively to bs then let's update it to
54
* point directly to bs (else it will become NULL). */
55
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
56
}
57
58
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
59
- &child_backing, 0, errp);
60
+ &child_of_bds, bdrv_backing_role(bs), errp);
61
if (!backing_hd) {
62
bs->open_flags |= BDRV_O_NO_BACKING;
63
error_prepend(errp, "Could not open backing file: ");
64
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
65
if (state->replace_backing_bs && state->new_backing_bs) {
66
uint64_t nperm, nshared;
67
bdrv_child_perm(state->bs, state->new_backing_bs,
68
- NULL, &child_backing, 0, bs_queue,
69
- state->perm, state->shared_perm,
70
+ NULL, &child_of_bds, bdrv_backing_role(state->bs),
71
+ bs_queue, state->perm, state->shared_perm,
72
&nperm, &nshared);
73
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
74
nperm, nshared, NULL, NULL, errp);
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
75
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
58
BlockDriver *drv = bs->drv;
76
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
59
BdrvChild *child;
77
} else {
60
QDict *opts;
78
QLIST_FOREACH(child, &bs->children, next) {
61
+ bool backing_overridden;
79
- if (child->klass == &child_backing && !backing_overridden) {
62
80
+ if (child == bs->backing && !backing_overridden) {
63
if (!drv) {
81
/* We can skip the backing BDS if it has not been overridden */
64
return;
82
continue;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
83
}
84
diff --git a/block/backup-top.c b/block/backup-top.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/backup-top.c
87
+++ b/block/backup-top.c
88
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
66
return;
89
return;
67
}
90
}
68
91
69
+ backing_overridden = bdrv_backing_overridden(bs);
92
- if (child_class == &child_file) {
70
+
93
+ if (!(role & BDRV_CHILD_FILTERED)) {
71
+ if (bs->open_flags & BDRV_O_NO_IO) {
94
/*
72
+ /* Without I/O, the backing file does not change anything.
95
* Target child
73
+ * Therefore, in such a case (primarily qemu-img), we can
96
*
74
+ * pretend the backing file has not been overridden even if
97
diff --git a/block/vvfat.c b/block/vvfat.c
75
+ * it technically has been. */
76
+ backing_overridden = false;
77
+ }
78
+
79
if (drv->bdrv_refresh_filename) {
80
/* Obsolete information is of no use here, so drop the old file name
81
* information before refreshing it */
82
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
83
84
opts = qdict_new();
85
has_open_options = append_open_options(opts, bs);
86
+ has_open_options |= backing_overridden;
87
88
/* If no specific options have been given for this BDS, the filename of
89
* the underlying file should suffice for this one as well */
90
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
91
* file BDS. The full options QDict of that file BDS should somehow
92
* contain a representation of the filename, therefore the following
93
* suffices without querying the (exact_)filename of this BDS. */
94
- if (bs->file->bs->full_open_options) {
95
+ if (bs->file->bs->full_open_options &&
96
+ (!bs->backing || bs->backing->bs->full_open_options))
97
+ {
98
qdict_put_str(opts, "driver", drv->format_name);
99
qdict_put(opts, "file",
100
qobject_ref(bs->file->bs->full_open_options));
101
102
+ if (bs->backing) {
103
+ qdict_put(opts, "backing",
104
+ qobject_ref(bs->backing->bs->full_open_options));
105
+ } else if (backing_overridden) {
106
+ qdict_put_null(opts, "backing");
107
+ }
108
+
109
bs->full_open_options = opts;
110
} else {
111
qobject_unref(opts);
112
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
113
index XXXXXXX..XXXXXXX 100644
98
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/qemu-iotests/051.out
99
--- a/block/vvfat.c
115
+++ b/tests/qemu-iotests/051.out
100
+++ b/block/vvfat.c
116
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
101
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
117
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
102
{
118
QEMU X.Y.Z monitor - type 'help' for more information
103
BDRVVVFATState *s = bs->opaque;
119
(qemu) info block
104
120
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
105
- assert(c == s->qcow || child_class == &child_backing);
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)
106
+ assert(c == s->qcow ||
122
Removable device: not locked, tray closed
107
+ (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
123
Cache mode: writeback
108
124
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
109
if (c == s->qcow) {
125
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
110
/* This is a private node, nobody should try to attach to it */
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
111
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
127
QEMU X.Y.Z monitor - type 'help' for more information
128
(qemu) info block
129
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
130
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
131
Removable device: not locked, tray closed
132
Cache mode: writeback
133
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
134
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
135
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
136
QEMU X.Y.Z monitor - type 'help' for more information
137
(qemu) info block
138
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
139
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
140
Removable device: not locked, tray closed
141
Cache mode: writethrough
142
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
143
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
144
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
145
QEMU X.Y.Z monitor - type 'help' for more information
146
(qemu) info block
147
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
148
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
149
Removable device: not locked, tray closed
150
Cache mode: writeback, ignore flushes
151
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
152
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
153
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
154
--- a/tests/qemu-iotests/051.pc.out
113
--- a/tests/test-bdrv-drain.c
155
+++ b/tests/qemu-iotests/051.pc.out
114
+++ b/tests/test-bdrv-drain.c
156
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
115
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
157
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
116
* bdrv_format_default_perms() accepts only these two, so disguise
158
QEMU X.Y.Z monitor - type 'help' for more information
117
* detach_by_driver_cb_parent as one of them.
159
(qemu) info block
118
*/
160
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
119
- if (child_class != &child_file && child_class != &child_backing) {
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)
120
+ if (child_class != &child_file && child_class != &child_of_bds) {
162
Removable device: not locked, tray closed
121
child_class = &child_file;
163
Cache mode: writeback
122
}
164
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
123
165
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
124
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
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
125
bdrv_ref(a);
167
QEMU X.Y.Z monitor - type 'help' for more information
126
child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
168
(qemu) info block
127
&error_abort);
169
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
128
- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, 0,
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)
129
- &error_abort);
171
Removable device: not locked, tray closed
130
+ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds,
172
Cache mode: writeback
131
+ BDRV_CHILD_COW, &error_abort);
173
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
132
174
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
133
bdrv_ref(a);
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
134
bdrv_attach_child(parent_a, a, "PA-A",
176
QEMU X.Y.Z monitor - type 'help' for more information
135
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
177
(qemu) info block
136
int i;
178
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
137
int ret;
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)
138
180
Removable device: not locked, tray closed
139
- chain_child_class = child_backing;
181
Cache mode: writethrough
140
+ chain_child_class = child_of_bds;
182
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
141
chain_child_class.update_filename = drop_intermediate_poll_update_filename;
183
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
142
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
143
for (i = 0; i < 3; i++) {
185
QEMU X.Y.Z monitor - type 'help' for more information
144
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
186
(qemu) info block
145
/* Takes the reference to chain[i - 1] */
187
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
146
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
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)
147
"chain", &chain_child_class,
189
Removable device: not locked, tray closed
148
- 0, &error_abort);
190
Cache mode: writeback, ignore flushes
149
+ BDRV_CHILD_COW, &error_abort);
191
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
150
}
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
154
155
bdrv_ref(old_child_bs);
156
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
157
- &child_backing, 0, &error_abort);
158
+ &child_of_bds, BDRV_CHILD_COW,
159
+ &error_abort);
160
161
for (i = 0; i < old_drain_count; i++) {
162
bdrv_drained_begin(old_child_bs);
192
--
163
--
193
2.20.1
164
2.25.4
194
165
195
166
diff view generated by jsdifflib
1
Now that bdrv_set_aio_context() works inside drained sections, it can
1
From: Max Reitz <mreitz@redhat.com>
2
also use the real drain function instead of open coding something
3
similar.
4
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-Id: <20200513110544.176672-25-mreitz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
---
7
block.c | 15 ++++++---------
8
include/block/block_int.h | 1 -
8
1 file changed, 6 insertions(+), 9 deletions(-)
9
block.c | 60 ++-------------------------------------
10
2 files changed, 3 insertions(+), 58 deletions(-)
9
11
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block_int.h
15
+++ b/include/block/block_int.h
16
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
17
18
extern const BdrvChildClass child_of_bds;
19
extern const BdrvChildClass child_file;
20
-extern const BdrvChildClass child_backing;
21
22
struct BdrvChild {
23
BlockDriverState *bs;
10
diff --git a/block.c b/block.c
24
diff --git a/block.c b/block.c
11
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
12
--- a/block.c
26
--- a/block.c
13
+++ b/block.c
27
+++ b/block.c
14
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
28
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
15
bs->walking_aio_notifiers = false;
29
parent->backing_blocker);
16
}
30
}
17
31
18
+/* The caller must own the AioContext lock for the old AioContext of bs, but it
32
-/* XXX: Will be removed along with child_backing */
19
+ * must not own the AioContext lock for new_context (unless new_context is
33
-static void bdrv_child_cb_attach_backing(BdrvChild *c)
20
+ * the same as the current context of bs). */
34
-{
21
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
35
- if (!(c->role & BDRV_CHILD_COW)) {
36
- bdrv_backing_attach(c);
37
- }
38
- bdrv_child_cb_attach(c);
39
-}
40
-
41
static void bdrv_backing_detach(BdrvChild *c)
22
{
42
{
23
- AioContext *ctx = bdrv_get_aio_context(bs);
43
BlockDriverState *parent = c->opaque;
44
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_detach(BdrvChild *c)
45
parent->backing_blocker = NULL;
46
}
47
48
-/* XXX: Will be removed along with child_backing */
49
-static void bdrv_child_cb_detach_backing(BdrvChild *c)
50
-{
51
- if (!(c->role & BDRV_CHILD_COW)) {
52
- bdrv_backing_detach(c);
53
- }
54
- bdrv_child_cb_detach(c);
55
-}
24
-
56
-
25
- if (ctx == new_context) {
57
-/*
26
+ if (bdrv_get_aio_context(bs) == new_context) {
58
- * Returns the options and flags that bs->backing should get, based on the
59
- * given options and flags for the parent BDS
60
- */
61
-static void bdrv_backing_options(BdrvChildRole role, bool parent_is_format,
62
- int *child_flags, QDict *child_options,
63
- int parent_flags, QDict *parent_options)
64
-{
65
- bdrv_inherited_options(BDRV_CHILD_COW, true,
66
- child_flags, child_options,
67
- parent_flags, parent_options);
68
-}
69
-
70
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
71
const char *filename, Error **errp)
72
{
73
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
74
return ret;
75
}
76
77
-const BdrvChildClass child_backing = {
78
- .parent_is_bds = true,
79
- .get_parent_desc = bdrv_child_get_parent_desc,
80
- .attach = bdrv_child_cb_attach_backing,
81
- .detach = bdrv_child_cb_detach_backing,
82
- .inherit_options = bdrv_backing_options,
83
- .drained_begin = bdrv_child_cb_drained_begin,
84
- .drained_poll = bdrv_child_cb_drained_poll,
85
- .drained_end = bdrv_child_cb_drained_end,
86
- .inactivate = bdrv_child_cb_inactivate,
87
- .update_filename = bdrv_backing_update_filename,
88
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
89
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
90
-};
91
-
92
/*
93
* Returns the options and flags that a generic child of a BDS should
94
* get, based on the given options and flags for the parent BDS.
95
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
96
uint64_t perm, uint64_t shared,
97
uint64_t *nperm, uint64_t *nshared)
98
{
99
- assert(child_class == &child_backing ||
100
- (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
101
+ assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW));
102
103
/*
104
* We want consistent read from backing files if the parent needs it.
105
@@ -XXX,XX +XXX,XX @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
106
uint64_t perm, uint64_t shared,
107
uint64_t *nperm, uint64_t *nshared)
108
{
109
- bool backing = (child_class == &child_backing);
110
-
111
if (child_class == &child_of_bds) {
112
bdrv_default_perms(bs, c, child_class, role, reopen_queue,
113
perm, shared, nperm, nshared);
27
return;
114
return;
28
}
115
}
29
116
30
- aio_disable_external(ctx);
117
- assert(child_class == &child_backing || child_class == &child_file);
31
- bdrv_parent_drained_begin(bs, NULL, false);
118
+ assert(child_class == &child_file);
32
- bdrv_drain(bs); /* ensure there are no in-flight requests */
119
33
-
120
- if (!backing) {
34
+ bdrv_drained_begin(bs);
121
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
35
bdrv_detach_aio_context(bs);
122
- perm, shared, nperm, nshared);
36
123
- } else {
37
/* This function executes in the old AioContext so acquire the new one in
124
- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
38
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
125
+ bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
39
*/
126
perm, shared, nperm, nshared);
40
aio_context_acquire(new_context);
127
- }
41
bdrv_attach_aio_context(bs, new_context);
42
- bdrv_parent_drained_end(bs, NULL, false);
43
- aio_enable_external(ctx);
44
+ bdrv_drained_end(bs);
45
aio_context_release(new_context);
46
}
128
}
47
129
130
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
48
--
131
--
49
2.20.1
132
2.25.4
50
133
51
134
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Besides being safe for arbitrary path lengths, after some follow-up
3
Commonly, they need to pass the BDRV_CHILD_IMAGE set as the
4
patches all callers will want a freshly allocated buffer anyway.
4
BdrvChildRole; but there are exceptions for drivers with external data
5
5
files (qcow2 and vmdk).
6
In the meantime, path_combine_deprecated() is added which has the same
7
interface as path_combine() had before this patch. All callers to that
8
function will be converted in follow-up patches.
9
6
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20200513110544.176672-26-mreitz@redhat.com>
13
Message-id: 20190201192935.18394-10-mreitz@redhat.com
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
11
---
16
include/block/block.h | 4 +-
12
block/bochs.c | 4 ++--
17
block.c | 85 ++++++++++++++++++++++++-------------------
13
block/cloop.c | 4 ++--
18
block/vmdk.c | 3 +-
14
block/crypto.c | 4 ++--
19
3 files changed, 49 insertions(+), 43 deletions(-)
15
block/dmg.c | 4 ++--
20
16
block/parallels.c | 4 ++--
21
diff --git a/include/block/block.h b/include/block/block.h
17
block/qcow.c | 4 ++--
22
index XXXXXXX..XXXXXXX 100644
18
block/qcow2.c | 19 +++++++++++++------
23
--- a/include/block/block.h
19
block/qed.c | 4 ++--
24
+++ b/include/block/block.h
20
block/vdi.c | 4 ++--
25
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
21
block/vhdx.c | 4 ++--
26
22
block/vmdk.c | 20 +++++++++++++++++---
27
int path_has_protocol(const char *path);
23
block/vpc.c | 4 ++--
28
int path_is_absolute(const char *path);
24
12 files changed, 50 insertions(+), 29 deletions(-)
29
-void path_combine(char *dest, int dest_size,
25
30
- const char *base_path,
26
diff --git a/block/bochs.c b/block/bochs.c
31
- const char *filename);
27
index XXXXXXX..XXXXXXX 100644
32
+char *path_combine(const char *base_path, const char *filename);
28
--- a/block/bochs.c
33
29
+++ b/block/bochs.c
34
int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
30
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
35
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
31
return ret;
36
diff --git a/block.c b/block.c
32
}
37
index XXXXXXX..XXXXXXX 100644
33
38
--- a/block.c
34
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
39
+++ b/block.c
35
- false, errp);
40
@@ -XXX,XX +XXX,XX @@ int path_is_absolute(const char *path)
36
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
41
#endif
37
+ BDRV_CHILD_IMAGE, false, errp);
42
}
38
if (!bs->file) {
43
39
return -EINVAL;
44
-/* if filename is absolute, just copy it to dest. Otherwise, build a
40
}
45
+/* if filename is absolute, just return its duplicate. Otherwise, build a
41
diff --git a/block/cloop.c b/block/cloop.c
46
path to it by considering it is relative to base_path. URL are
42
index XXXXXXX..XXXXXXX 100644
47
supported. */
43
--- a/block/cloop.c
48
-void path_combine(char *dest, int dest_size,
44
+++ b/block/cloop.c
49
- const char *base_path,
45
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
50
- const char *filename)
46
return ret;
51
+char *path_combine(const char *base_path, const char *filename)
47
}
52
{
48
53
+ const char *protocol_stripped = NULL;
49
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
54
const char *p, *p1;
50
- false, errp);
55
+ char *result;
51
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
56
int len;
52
+ BDRV_CHILD_IMAGE, false, errp);
57
53
if (!bs->file) {
58
- if (dest_size <= 0)
54
return -EINVAL;
59
- return;
55
}
60
if (path_is_absolute(filename)) {
56
diff --git a/block/crypto.c b/block/crypto.c
61
- pstrcpy(dest, dest_size, filename);
57
index XXXXXXX..XXXXXXX 100644
62
- } else {
58
--- a/block/crypto.c
63
- const char *protocol_stripped = NULL;
59
+++ b/block/crypto.c
64
+ return g_strdup(filename);
60
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
65
+ }
61
unsigned int cflags = 0;
66
62
QDict *cryptoopts = NULL;
67
- if (path_has_protocol(base_path)) {
63
68
- protocol_stripped = strchr(base_path, ':');
64
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
69
- if (protocol_stripped) {
65
- false, errp);
70
- protocol_stripped++;
66
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
71
- }
67
+ BDRV_CHILD_IMAGE, false, errp);
72
+ if (path_has_protocol(base_path)) {
68
if (!bs->file) {
73
+ protocol_stripped = strchr(base_path, ':');
69
return -EINVAL;
74
+ if (protocol_stripped) {
70
}
75
+ protocol_stripped++;
71
diff --git a/block/dmg.c b/block/dmg.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/block/dmg.c
74
+++ b/block/dmg.c
75
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
76
return ret;
77
}
78
79
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
80
- false, errp);
81
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
82
+ BDRV_CHILD_IMAGE, false, errp);
83
if (!bs->file) {
84
return -EINVAL;
85
}
86
diff --git a/block/parallels.c b/block/parallels.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/parallels.c
89
+++ b/block/parallels.c
90
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
91
Error *local_err = NULL;
92
char *buf;
93
94
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
95
- false, errp);
96
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
97
+ BDRV_CHILD_IMAGE, false, errp);
98
if (!bs->file) {
99
return -EINVAL;
100
}
101
diff --git a/block/qcow.c b/block/qcow.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/block/qcow.c
104
+++ b/block/qcow.c
105
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
106
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
107
encryptfmt = qdict_get_try_str(encryptopts, "format");
108
109
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
110
- false, errp);
111
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
112
+ BDRV_CHILD_IMAGE, false, errp);
113
if (!bs->file) {
114
ret = -EINVAL;
115
goto fail;
116
diff --git a/block/qcow2.c b/block/qcow2.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/qcow2.c
119
+++ b/block/qcow2.c
120
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
121
}
122
123
/* Open external data file */
124
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file,
125
- 0, true, &local_err);
126
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
127
+ &child_of_bds, BDRV_CHILD_DATA,
128
+ true, &local_err);
129
if (local_err) {
130
error_propagate(errp, local_err);
131
ret = -EINVAL;
132
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
133
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
134
if (!s->data_file && s->image_data_file) {
135
s->data_file = bdrv_open_child(s->image_data_file, options,
136
- "data-file", bs, &child_file, 0,
137
- false, errp);
138
+ "data-file", bs, &child_of_bds,
139
+ BDRV_CHILD_DATA, false, errp);
140
if (!s->data_file) {
141
ret = -EINVAL;
142
goto fail;
143
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
144
ret = -EINVAL;
145
goto fail;
76
}
146
}
77
- p = protocol_stripped ?: base_path;
147
+
78
+ }
148
+ /* No data here */
79
+ p = protocol_stripped ?: base_path;
149
+ bs->file->role &= ~BDRV_CHILD_DATA;
80
150
+
81
- p1 = strrchr(base_path, '/');
151
+ /* Must succeed because we have given up permissions if anything */
82
+ p1 = strrchr(base_path, '/');
152
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
83
#ifdef _WIN32
84
- {
85
- const char *p2;
86
- p2 = strrchr(base_path, '\\');
87
- if (!p1 || p2 > p1)
88
- p1 = p2;
89
+ {
90
+ const char *p2;
91
+ p2 = strrchr(base_path, '\\');
92
+ if (!p1 || p2 > p1) {
93
+ p1 = p2;
94
}
95
+ }
96
#endif
97
- if (p1)
98
- p1++;
99
- else
100
- p1 = base_path;
101
- if (p1 > p)
102
- p = p1;
103
- len = p - base_path;
104
- if (len > dest_size - 1)
105
- len = dest_size - 1;
106
- memcpy(dest, base_path, len);
107
- dest[len] = '\0';
108
- pstrcat(dest, dest_size, filename);
109
+ if (p1) {
110
+ p1++;
111
+ } else {
112
+ p1 = base_path;
113
+ }
114
+ if (p1 > p) {
115
+ p = p1;
116
}
117
+ len = p - base_path;
118
+
119
+ result = g_malloc(len + strlen(filename) + 1);
120
+ memcpy(result, base_path, len);
121
+ strcpy(result + len, filename);
122
+
123
+ return result;
124
+}
125
+
126
+static void path_combine_deprecated(char *dest, int dest_size,
127
+ const char *base_path,
128
+ const char *filename)
129
+{
130
+ char *combined = path_combine(base_path, filename);
131
+ pstrcpy(dest, dest_size, combined);
132
+ g_free(combined);
133
}
134
135
/*
136
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
137
error_setg(errp, "Cannot use relative backing file names for '%s'",
138
backed);
139
} else {
153
} else {
140
- path_combine(dest, sz, backed, backing);
154
if (s->data_file) {
141
+ path_combine_deprecated(dest, sz, backed, backing);
155
error_setg(errp, "'data-file' can only be set for images with an "
142
}
156
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
143
}
157
.ret = -EINPROGRESS
144
158
};
145
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
159
146
} else {
160
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
147
/* If not an absolute filename path, make it relative to the current
161
- false, errp);
148
* image's filename path */
162
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
149
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
163
+ BDRV_CHILD_IMAGE, false, errp);
150
- backing_file);
164
if (!bs->file) {
151
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
165
return -EINVAL;
152
+ backing_file);
166
}
153
167
diff --git a/block/qed.c b/block/qed.c
154
/* We are going to compare absolute pathnames */
168
index XXXXXXX..XXXXXXX 100644
155
if (!realpath(filename_tmp, filename_full)) {
169
--- a/block/qed.c
156
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
170
+++ b/block/qed.c
157
171
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
158
/* We need to make sure the backing filename we are comparing against
172
.ret = -EINPROGRESS
159
* is relative to the current image filename (or absolute) */
173
};
160
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
174
161
- curr_bs->backing_file);
175
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
162
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
176
- false, errp);
163
+ curr_bs->backing_file);
177
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
164
178
+ BDRV_CHILD_IMAGE, false, errp);
165
if (!realpath(filename_tmp, backing_file_full)) {
179
if (!bs->file) {
166
continue;
180
return -EINVAL;
181
}
182
diff --git a/block/vdi.c b/block/vdi.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/vdi.c
185
+++ b/block/vdi.c
186
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
187
Error *local_err = NULL;
188
QemuUUID uuid_link, uuid_parent;
189
190
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
191
- false, errp);
192
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
193
+ BDRV_CHILD_IMAGE, false, errp);
194
if (!bs->file) {
195
return -EINVAL;
196
}
197
diff --git a/block/vhdx.c b/block/vhdx.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/block/vhdx.c
200
+++ b/block/vhdx.c
201
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
202
uint64_t signature;
203
Error *local_err = NULL;
204
205
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
206
- false, errp);
207
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
208
+ BDRV_CHILD_IMAGE, false, errp);
209
if (!bs->file) {
210
return -EINVAL;
211
}
167
diff --git a/block/vmdk.c b/block/vmdk.c
212
diff --git a/block/vmdk.c b/block/vmdk.c
168
index XXXXXXX..XXXXXXX 100644
213
index XXXXXXX..XXXXXXX 100644
169
--- a/block/vmdk.c
214
--- a/block/vmdk.c
170
+++ b/block/vmdk.c
215
+++ b/block/vmdk.c
171
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
216
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
172
return -EINVAL;
217
char *desc_file_dir = NULL;
173
}
218
char *extent_path;
174
219
BdrvChild *extent_file;
175
- extent_path = g_malloc0(PATH_MAX);
220
+ BdrvChildRole extent_role;
176
- path_combine(extent_path, PATH_MAX, desc_file_path, fname);
221
BDRVVmdkState *s = bs->opaque;
177
+ extent_path = path_combine(desc_file_path, fname);
222
VmdkExtent *extent;
178
223
char extent_opt_prefix[32];
224
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
179
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
225
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
180
assert(ret < 32);
226
assert(ret < 32);
227
228
+ extent_role = BDRV_CHILD_DATA;
229
+ if (strcmp(type, "FLAT") != 0 && strcmp(type, "VMFS") != 0) {
230
+ /* non-flat extents have metadata */
231
+ extent_role |= BDRV_CHILD_METADATA;
232
+ }
233
+
234
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
235
- bs, &child_file, 0, false, &local_err);
236
+ bs, &child_of_bds, extent_role, false,
237
+ &local_err);
238
g_free(extent_path);
239
if (local_err) {
240
error_propagate(errp, local_err);
241
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
242
uint32_t magic;
243
Error *local_err = NULL;
244
245
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
246
- false, errp);
247
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
248
+ BDRV_CHILD_IMAGE, false, errp);
249
if (!bs->file) {
250
return -EINVAL;
251
}
252
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
253
s->desc_offset = 0x200;
254
break;
255
default:
256
+ /* No data in the descriptor file */
257
+ bs->file->role &= ~BDRV_CHILD_DATA;
258
+
259
+ /* Must succeed because we have given up permissions if anything */
260
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
261
+
262
ret = vmdk_open_desc_file(bs, flags, buf, options, errp);
263
break;
264
}
265
diff --git a/block/vpc.c b/block/vpc.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/vpc.c
268
+++ b/block/vpc.c
269
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
270
int ret;
271
int64_t bs_size;
272
273
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
274
- false, errp);
275
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
276
+ BDRV_CHILD_IMAGE, false, errp);
277
if (!bs->file) {
278
return -EINVAL;
279
}
181
--
280
--
182
2.20.1
281
2.25.4
183
282
184
283
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
blkverify's BDSs have a file BDS, but we do not want this to be
3
Note that some filters have secondary children, namely blkverify (the
4
preferred over the raw node. There is no way to decide between the two
4
image to be verified) and blklogwrites (the log). This patch does not
5
(and not really a reason to, either), so just return NULL in blkverify's
5
touch those children.
6
implementation of bdrv_dirname().
6
7
Note that for blkverify, the filtered child should not be format-probed.
8
While there is nothing enforcing this here, in practice, it will not be:
9
blkverify implements .bdrv_file_open. The block layer ensures (and in
10
fact, asserts) that BDRV_O_PROTOCOL is set for every BDS whose driver
11
implements .bdrv_file_open. This flag will then be bequeathed to
12
blkverify's children, and they will thus (by default) not be probed
13
either.
14
15
("By default" refers to the fact that blkverify's other child (the
16
non-filtered one) will have BDRV_O_PROTOCOL force-unset, because that is
17
what happens for all non-filtered children of non-format drivers.)
7
18
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Message-Id: <20200513110544.176672-27-mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-id: 20190201192935.18394-16-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
23
---
14
block/blkverify.c | 10 ++++++++++
24
block/blkdebug.c | 4 +++-
15
1 file changed, 10 insertions(+)
25
block/blklogwrites.c | 3 ++-
26
block/blkreplay.c | 5 +++--
27
block/blkverify.c | 4 +++-
28
block/copy-on-read.c | 5 +++--
29
block/filter-compress.c | 5 +++--
30
block/replication.c | 3 ++-
31
block/throttle.c | 5 +++--
32
8 files changed, 22 insertions(+), 12 deletions(-)
16
33
34
diff --git a/block/blkdebug.c b/block/blkdebug.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/blkdebug.c
37
+++ b/block/blkdebug.c
38
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
39
40
/* Open the image file */
41
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
42
- bs, &child_file, 0, false, &local_err);
43
+ bs, &child_of_bds,
44
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
45
+ false, &local_err);
46
if (local_err) {
47
ret = -EINVAL;
48
error_propagate(errp, local_err);
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 int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
54
}
55
56
/* Open the file */
57
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
58
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
59
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
60
&local_err);
61
if (local_err) {
62
ret = -EINVAL;
63
diff --git a/block/blkreplay.c b/block/blkreplay.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/blkreplay.c
66
+++ b/block/blkreplay.c
67
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
68
int ret;
69
70
/* Open the image file */
71
- bs->file = bdrv_open_child(NULL, options, "image",
72
- bs, &child_file, 0, false, &local_err);
73
+ bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
74
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
75
+ false, &local_err);
76
if (local_err) {
77
ret = -EINVAL;
78
error_propagate(errp, local_err);
17
diff --git a/block/blkverify.c b/block/blkverify.c
79
diff --git a/block/blkverify.c b/block/blkverify.c
18
index XXXXXXX..XXXXXXX 100644
80
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
81
--- a/block/blkverify.c
20
+++ b/block/blkverify.c
82
+++ b/block/blkverify.c
21
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
83
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
84
85
/* Open the raw file */
86
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
87
- bs, &child_file, 0, false, &local_err);
88
+ bs, &child_of_bds,
89
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
90
+ false, &local_err);
91
if (local_err) {
92
ret = -EINVAL;
93
error_propagate(errp, local_err);
94
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/copy-on-read.c
97
+++ b/block/copy-on-read.c
98
@@ -XXX,XX +XXX,XX @@
99
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
100
Error **errp)
101
{
102
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
103
- errp);
104
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
105
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
106
+ false, errp);
107
if (!bs->file) {
108
return -EINVAL;
22
}
109
}
23
}
110
diff --git a/block/filter-compress.c b/block/filter-compress.c
24
111
index XXXXXXX..XXXXXXX 100644
25
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
112
--- a/block/filter-compress.c
26
+{
113
+++ b/block/filter-compress.c
27
+ /* In general, there are two BDSs with different dirnames below this one;
114
@@ -XXX,XX +XXX,XX @@
28
+ * so there is no unique dirname we could return (unless both are equal by
115
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
29
+ * chance). Therefore, to be consistent, just always return NULL. */
116
Error **errp)
30
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
117
{
31
+ return NULL;
118
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0, false,
32
+}
119
- errp);
33
+
120
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
34
static BlockDriver bdrv_blkverify = {
121
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
35
.format_name = "blkverify",
122
+ false, errp);
36
.protocol_name = "blkverify",
123
if (!bs->file) {
37
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
124
return -EINVAL;
38
.bdrv_child_perm = bdrv_filter_default_perms,
125
}
39
.bdrv_getlength = blkverify_getlength,
126
diff --git a/block/replication.c b/block/replication.c
40
.bdrv_refresh_filename = blkverify_refresh_filename,
127
index XXXXXXX..XXXXXXX 100644
41
+ .bdrv_dirname = blkverify_dirname,
128
--- a/block/replication.c
42
129
+++ b/block/replication.c
43
.bdrv_co_preadv = blkverify_co_preadv,
130
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
44
.bdrv_co_pwritev = blkverify_co_pwritev,
131
const char *mode;
132
const char *top_id;
133
134
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
135
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
136
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
137
false, errp);
138
if (!bs->file) {
139
return -EINVAL;
140
diff --git a/block/throttle.c b/block/throttle.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/throttle.c
143
+++ b/block/throttle.c
144
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
145
char *group;
146
int ret;
147
148
- bs->file = bdrv_open_child(NULL, options, "file", bs,
149
- &child_file, 0, false, errp);
150
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
151
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
152
+ false, errp);
153
if (!bs->file) {
154
return -EINVAL;
155
}
45
--
156
--
46
2.20.1
157
2.25.4
47
158
48
159
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Before this patch, bdrv_refresh_filename() is used in a pushing manner:
3
Replace child_file by child_of_bds in all remaining places (excluding
4
Whenever the BDS graph is modified, the parents of the modified edges
4
tests).
5
are supposed to be updated (recursively upwards). However, that is
6
nonviable, considering that we want child changes not to concern
7
parents.
8
9
Also, in the long run we want a pull model anyway: Here, we would have a
10
bdrv_filename() function which returns a BDS's filename, freshly
11
constructed.
12
13
This patch is an intermediate step. It adds bdrv_refresh_filename()
14
calls before every place a BDS.filename value is used. The only
15
exceptions are protocol drivers that use their own filename, which
16
clearly would not profit from refreshing that filename before.
17
18
Also, bdrv_get_encrypted_filename() is removed along the way (as a user
19
of BDS.filename), since it is completely unused.
20
21
In turn, all of the calls to bdrv_refresh_filename() before this patch
22
are removed, because we no longer have to call this function on graph
23
changes.
24
5
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
Message-id: 20190201192935.18394-2-mreitz@redhat.com
7
Message-Id: <20200513110544.176672-28-mreitz@redhat.com>
27
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29
---
10
---
30
include/block/block.h | 1 -
11
block.c | 3 ++-
31
block.c | 31 +++++++++++++++----------------
12
block/backup-top.c | 4 ++--
32
block/qapi.c | 4 ++++
13
block/blklogwrites.c | 4 ++--
33
block/raw-format.c | 1 +
14
block/raw-format.c | 15 +++++++++++++--
34
block/replication.c | 2 --
15
4 files changed, 19 insertions(+), 7 deletions(-)
35
block/vhdx-log.c | 1 +
36
block/vmdk.c | 6 ++++++
37
blockdev.c | 8 ++++++++
38
qemu-img.c | 11 +++++++++--
39
9 files changed, 44 insertions(+), 21 deletions(-)
40
16
41
diff --git a/include/block/block.h b/include/block/block.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block.h
44
+++ b/include/block/block.h
45
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
46
int64_t *cluster_offset,
47
int64_t *cluster_bytes);
48
49
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs);
50
void bdrv_get_backing_filename(BlockDriverState *bs,
51
char *filename, int filename_size);
52
void bdrv_get_full_backing_filename(BlockDriverState *bs,
53
diff --git a/block.c b/block.c
17
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
19
--- a/block.c
56
+++ b/block.c
20
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
21
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
58
void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
22
BlockDriverState *file_bs;
59
Error **errp)
23
60
{
24
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
61
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
25
- &child_file, 0, true, &local_err);
62
+ char *backed;
26
+ &child_of_bds, BDRV_CHILD_IMAGE,
63
27
+ true, &local_err);
64
+ bdrv_refresh_filename(bs);
28
if (local_err) {
65
+
29
goto fail;
66
+ backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
30
}
67
bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
31
diff --git a/block/backup-top.c b/block/backup-top.c
68
dest, sz, errp);
32
index XXXXXXX..XXXXXXX 100644
69
}
33
--- a/block/backup-top.c
70
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
34
+++ b/block/backup-top.c
71
"node is used as backing hd of '%s'",
35
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
72
bdrv_get_device_or_node_name(parent));
36
source->supported_zero_flags);
73
37
74
+ bdrv_refresh_filename(backing_hd);
38
bdrv_ref(target);
75
+
39
- state->target = bdrv_attach_child(top, target, "target", &child_file, 0,
76
parent->open_flags &= ~BDRV_O_NO_BACKING;
40
- errp);
77
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
41
+ state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
78
backing_hd->filename);
42
+ BDRV_CHILD_DATA, errp);
79
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
43
if (!state->target) {
44
bdrv_unref(target);
45
bdrv_unref(top);
46
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/blklogwrites.c
49
+++ b/block/blklogwrites.c
50
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
80
}
51
}
81
52
82
if (file != NULL) {
53
/* Open the log file */
83
+ bdrv_refresh_filename(blk_bs(file));
54
- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, 0,
84
filename = blk_bs(file)->filename;
55
- false, &local_err);
85
} else {
56
+ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_of_bds,
86
/*
57
+ BDRV_CHILD_METADATA, false, &local_err);
87
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
58
if (local_err) {
88
bdrv_unref(backing_hd);
59
ret = -EINVAL;
89
}
60
error_propagate(errp, local_err);
90
91
- bdrv_refresh_filename(bs);
92
-
93
out:
94
bdrv_refresh_limits(bs, NULL);
95
}
96
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
97
g_free(child_key_dot);
98
}
99
100
- bdrv_refresh_filename(bs);
101
-
102
/* Check if any unknown options were used */
103
if (qdict_size(options) != 0) {
104
const QDictEntry *entry = qdict_first(options);
105
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
106
if (local_err != NULL) {
107
error_propagate(errp, local_err);
108
} else {
109
+ bdrv_refresh_filename(reopen_state->bs);
110
error_setg(errp, "failed while preparing to reopen image '%s'",
111
reopen_state->bs->filename);
112
}
113
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
114
/* success - we can delete the intermediate states, and link top->base */
115
/* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
116
* we've figured out how they should work. */
117
- backing_file_str = backing_file_str ? backing_file_str : base->filename;
118
+ if (!backing_file_str) {
119
+ bdrv_refresh_filename(base);
120
+ backing_file_str = base->filename;
121
+ }
122
123
QLIST_FOREACH_SAFE(c, &top->parents, next_parent, next) {
124
/* Check whether we are allowed to switch c from top to base */
125
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
126
return bs->supported_zero_flags & BDRV_REQ_MAY_UNMAP;
127
}
128
129
-const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
130
-{
131
- if (bs->backing && bs->backing->bs->encrypted)
132
- return bs->backing_file;
133
- else if (bs->encrypted)
134
- return bs->filename;
135
- else
136
- return NULL;
137
-}
138
-
139
void bdrv_get_backing_filename(BlockDriverState *bs,
140
char *filename, int filename_size)
141
{
142
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
143
144
is_protocol = path_has_protocol(backing_file);
145
146
+ /* This will recursively refresh everything in the backing chain */
147
+ bdrv_refresh_filename(bs);
148
+
149
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
150
151
/* If either of the filename paths is actually a protocol, then
152
diff --git a/block/qapi.c b/block/qapi.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/qapi.c
155
+++ b/block/qapi.c
156
@@ -XXX,XX +XXX,XX @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
157
return NULL;
158
}
159
160
+ bdrv_refresh_filename(bs);
161
+
162
info = g_malloc0(sizeof(*info));
163
info->file = g_strdup(bs->filename);
164
info->ro = bs->read_only;
165
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
166
goto out;
167
}
168
169
+ bdrv_refresh_filename(bs);
170
+
171
info = g_new0(ImageInfo, 1);
172
info->filename = g_strdup(bs->filename);
173
info->format = g_strdup(bdrv_get_format_name(bs));
174
diff --git a/block/raw-format.c b/block/raw-format.c
61
diff --git a/block/raw-format.c b/block/raw-format.c
175
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
176
--- a/block/raw-format.c
63
--- a/block/raw-format.c
177
+++ b/block/raw-format.c
64
+++ b/block/raw-format.c
178
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
65
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
179
bs->file->bs->supported_zero_flags);
66
BDRVRawState *s = bs->opaque;
180
67
bool has_size;
181
if (bs->probed && !bdrv_is_read_only(bs)) {
68
uint64_t offset, size;
182
+ bdrv_refresh_filename(bs->file->bs);
69
+ BdrvChildRole file_role;
183
fprintf(stderr,
70
int ret;
184
"WARNING: Image format was not specified for '%s' and probing "
71
185
"guessed raw.\n"
72
ret = raw_read_options(options, &offset, &has_size, &size, errp);
186
diff --git a/block/replication.c b/block/replication.c
73
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
187
index XXXXXXX..XXXXXXX 100644
74
return ret;
188
--- a/block/replication.c
189
+++ b/block/replication.c
190
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
191
if (ret == 0) {
192
s->stage = BLOCK_REPLICATION_DONE;
193
194
- /* refresh top bs's filename */
195
- bdrv_refresh_filename(bs);
196
s->active_disk = NULL;
197
s->secondary_disk = NULL;
198
s->hidden_disk = NULL;
199
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/vhdx-log.c
202
+++ b/block/vhdx-log.c
203
@@ -XXX,XX +XXX,XX @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
204
205
if (logs.valid) {
206
if (bs->read_only) {
207
+ bdrv_refresh_filename(bs);
208
ret = -EPERM;
209
error_setg(errp,
210
"VHDX image file '%s' opened read-only, but "
211
diff --git a/block/vmdk.c b/block/vmdk.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/block/vmdk.c
214
+++ b/block/vmdk.c
215
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
216
extent->l1_table,
217
l1_size);
218
if (ret < 0) {
219
+ bdrv_refresh_filename(extent->file->bs);
220
error_setg_errno(errp, -ret,
221
"Could not read l1 table from extent '%s'",
222
extent->file->bs->filename);
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
224
extent->l1_backup_table,
225
l1_size);
226
if (ret < 0) {
227
+ bdrv_refresh_filename(extent->file->bs);
228
error_setg_errno(errp, -ret,
229
"Could not read l1 backup table from extent '%s'",
230
extent->file->bs->filename);
231
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
232
233
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
234
if (ret < 0) {
235
+ bdrv_refresh_filename(file->bs);
236
error_setg_errno(errp, -ret,
237
"Could not read header from file '%s'",
238
file->bs->filename);
239
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
240
241
ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
242
if (ret < 0) {
243
+ bdrv_refresh_filename(file->bs);
244
error_setg_errno(errp, -ret,
245
"Could not read header from file '%s'",
246
file->bs->filename);
247
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
248
if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
249
!desc_file_path[0])
250
{
251
+ bdrv_refresh_filename(bs->file->bs);
252
error_setg(errp, "Cannot use relative extent paths with VMDK "
253
"descriptor file '%s'", bs->file->bs->filename);
254
return -EINVAL;
255
@@ -XXX,XX +XXX,XX @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
256
{
257
ImageInfo *info = g_new0(ImageInfo, 1);
258
259
+ bdrv_refresh_filename(extent->file->bs);
260
*info = (ImageInfo){
261
.filename = g_strdup(extent->file->bs->filename),
262
.format = g_strdup(extent->type),
263
diff --git a/blockdev.c b/blockdev.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/blockdev.c
266
+++ b/blockdev.c
267
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
268
error_setg_errno(errp, -size, "bdrv_getlength failed");
269
goto out;
270
}
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
}
278
assert(bdrv_get_aio_context(base_bs) == aio_context);
279
+ bdrv_refresh_filename(base_bs);
280
base_name = base_bs->filename;
281
}
75
}
282
76
283
@@ -XXX,XX +XXX,XX @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
77
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, 0,
284
goto out;
78
- false, errp);
285
}
79
+ /*
286
} else if (has_top && top) {
80
+ * Without offset and a size limit, this driver behaves very much
287
+ /* This strcmp() is just a shortcut, there is no need to
81
+ * like a filter. With any such limit, it does not.
288
+ * refresh @bs's filename. If it mismatches,
82
+ */
289
+ * bdrv_find_backing_image() will do the refresh and may still
83
+ if (offset || has_size) {
290
+ * return @bs. */
84
+ file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
291
if (strcmp(bs->filename, top) != 0) {
85
+ } else {
292
top_bs = bdrv_find_backing_image(bs, top);
86
+ file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
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
+ }
87
+ }
330
+
88
+
331
*e = (MapEntry) {
89
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
332
.start = offset,
90
+ file_role, false, errp);
333
.length = bytes,
91
if (!bs->file) {
334
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
92
return -EINVAL;
335
.offset = map,
93
}
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
--
94
--
354
2.20.1
95
2.25.4
355
96
356
97
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Message-Id: <20200513110544.176672-29-mreitz@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
7
---
4
tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++
8
tests/test-bdrv-drain.c | 29 +++++++++++++++++------------
5
1 file changed, 32 insertions(+)
9
tests/test-bdrv-graph-mod.c | 6 ++++--
10
2 files changed, 21 insertions(+), 14 deletions(-)
6
11
7
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
12
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
8
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
9
--- a/tests/test-bdrv-drain.c
14
--- a/tests/test-bdrv-drain.c
10
+++ b/tests/test-bdrv-drain.c
15
+++ b/tests/test-bdrv-drain.c
11
@@ -XXX,XX +XXX,XX @@ static void test_append_to_drained(void)
16
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
12
blk_unref(blk);
17
* detach_by_driver_cb_parent as one of them.
18
*/
19
if (child_class != &child_file && child_class != &child_of_bds) {
20
- child_class = &child_file;
21
+ child_class = &child_of_bds;
22
}
23
24
bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
25
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
26
27
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
28
&error_abort);
29
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
30
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds,
31
+ BDRV_CHILD_DATA, &error_abort);
32
33
/* This child will be the one to pass to requests through to, and
34
* it will stall until a drain occurs */
35
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
36
&error_abort);
37
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
38
/* Takes our reference to child_bs */
39
- tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file,
40
- 0, &error_abort);
41
+ tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child",
42
+ &child_of_bds,
43
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
44
+ &error_abort);
45
46
/* This child is just there to be deleted
47
* (for detach_instead_of_delete == true) */
48
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
49
&error_abort);
50
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, 0, &error_abort);
51
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA,
52
+ &error_abort);
53
54
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
55
blk_insert_bs(blk, bs, &error_abort);
56
@@ -XXX,XX +XXX,XX @@ static void detach_indirect_bh(void *opaque)
57
58
bdrv_ref(data->c);
59
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
60
- &child_file, 0, &error_abort);
61
+ &child_of_bds, BDRV_CHILD_DATA,
62
+ &error_abort);
13
}
63
}
14
64
15
+static void test_set_aio_context(void)
65
static void detach_by_parent_aio_cb(void *opaque, int ret)
16
+{
66
@@ -XXX,XX +XXX,XX @@ static void detach_by_driver_cb_drained_begin(BdrvChild *child)
17
+ BlockDriverState *bs;
18
+ IOThread *a = iothread_new();
19
+ IOThread *b = iothread_new();
20
+ AioContext *ctx_a = iothread_get_aio_context(a);
21
+ AioContext *ctx_b = iothread_get_aio_context(b);
22
+
23
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
24
+ &error_abort);
25
+
26
+ bdrv_drained_begin(bs);
27
+ bdrv_set_aio_context(bs, ctx_a);
28
+
29
+ aio_context_acquire(ctx_a);
30
+ bdrv_drained_end(bs);
31
+
32
+ bdrv_drained_begin(bs);
33
+ bdrv_set_aio_context(bs, ctx_b);
34
+ aio_context_release(ctx_a);
35
+ aio_context_acquire(ctx_b);
36
+ bdrv_set_aio_context(bs, qemu_get_aio_context());
37
+ aio_context_release(ctx_b);
38
+ bdrv_drained_end(bs);
39
+
40
+ bdrv_unref(bs);
41
+ iothread_join(a);
42
+ iothread_join(b);
43
+}
44
+
45
int main(int argc, char **argv)
46
{
67
{
47
int ret;
68
aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
69
detach_indirect_bh, &detach_by_parent_data);
49
70
- child_file.drained_begin(child);
50
g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
71
+ child_of_bds.drained_begin(child);
51
72
}
52
+ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context);
73
53
+
74
static BdrvChildClass detach_by_driver_cb_class;
54
ret = g_test_run();
75
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
55
qemu_event_destroy(&done_event);
76
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
56
return ret;
77
78
if (!by_parent_cb) {
79
- detach_by_driver_cb_class = child_file;
80
+ detach_by_driver_cb_class = child_of_bds;
81
detach_by_driver_cb_class.drained_begin =
82
detach_by_driver_cb_drained_begin;
83
}
84
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
85
/* Set child relationships */
86
bdrv_ref(b);
87
bdrv_ref(a);
88
- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, 0,
89
- &error_abort);
90
+ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds,
91
+ BDRV_CHILD_DATA, &error_abort);
92
child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds,
93
BDRV_CHILD_COW, &error_abort);
94
95
bdrv_ref(a);
96
bdrv_attach_child(parent_a, a, "PA-A",
97
- by_parent_cb ? &child_file : &detach_by_driver_cb_class,
98
- 0, &error_abort);
99
+ by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class,
100
+ BDRV_CHILD_DATA, &error_abort);
101
102
g_assert_cmpint(parent_a->refcnt, ==, 1);
103
g_assert_cmpint(parent_b->refcnt, ==, 1);
104
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/tests/test-bdrv-graph-mod.c
107
+++ b/tests/test-bdrv-graph-mod.c
108
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
109
110
blk_insert_bs(root, bs, &error_abort);
111
112
- bdrv_attach_child(filter, bs, "child", &child_file, 0, &error_abort);
113
+ bdrv_attach_child(filter, bs, "child", &child_of_bds,
114
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
115
116
bdrv_append(filter, bs, &local_err);
117
118
@@ -XXX,XX +XXX,XX @@ static void test_should_update_child(void)
119
bdrv_set_backing_hd(target, bs, &error_abort);
120
121
g_assert(target->backing->bs == bs);
122
- bdrv_attach_child(filter, target, "target", &child_file, 0, &error_abort);
123
+ bdrv_attach_child(filter, target, "target", &child_of_bds,
124
+ BDRV_CHILD_DATA, &error_abort);
125
bdrv_append(filter, bs, &error_abort);
126
g_assert(target->backing->bs == bs);
127
57
--
128
--
58
2.20.1
129
2.25.4
59
130
60
131
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
The generic bdrv_dirname() implementation would be able to generate some
3
bdrv_default_perms() can decide which permission profile to use based on
4
form of directory name for many NBD nodes, but it would be always wrong.
4
the BdrvChildRole, so block drivers do not need to select it explicitly.
5
Therefore, we have to explicitly make it an error (until NBD has some
5
6
form of specification for export paths, if it ever will).
6
The blkverify driver now no longer shares the WRITE permission for the
7
image to verify. We thus have to adjust two places in
8
test-block-iothread not to take it. (Note that in theory, blkverify
9
should behave like quorum in this regard and share neither WRITE nor
10
RESIZE for both of its children. In practice, it does not really
11
matter, because blkverify is used only for debugging, so we might as
12
well keep its permissions rather liberal.)
7
13
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20190201192935.18394-18-mreitz@redhat.com
16
Message-Id: <20200513110544.176672-30-mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
18
---
14
block/nbd.c | 13 +++++++++++++
19
block/backup-top.c | 4 ++--
15
1 file changed, 13 insertions(+)
20
block/blkdebug.c | 4 ++--
16
21
block/blklogwrites.c | 9 ++-------
17
diff --git a/block/nbd.c b/block/nbd.c
22
block/blkreplay.c | 2 +-
18
index XXXXXXX..XXXXXXX 100644
23
block/blkverify.c | 2 +-
19
--- a/block/nbd.c
24
block/bochs.c | 2 +-
20
+++ b/block/nbd.c
25
block/cloop.c | 2 +-
21
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
26
block/crypto.c | 2 +-
22
bs->full_open_options = opts;
27
block/dmg.c | 2 +-
28
block/filter-compress.c | 2 +-
29
block/parallels.c | 2 +-
30
block/qcow.c | 2 +-
31
block/qcow2.c | 2 +-
32
block/qed.c | 2 +-
33
block/raw-format.c | 2 +-
34
block/throttle.c | 2 +-
35
block/vdi.c | 2 +-
36
block/vhdx.c | 2 +-
37
block/vmdk.c | 2 +-
38
block/vpc.c | 2 +-
39
tests/test-bdrv-drain.c | 10 +++++-----
40
tests/test-bdrv-graph-mod.c | 2 +-
41
tests/test-block-iothread.c | 17 ++++++++++++++---
42
23 files changed, 43 insertions(+), 37 deletions(-)
43
44
diff --git a/block/backup-top.c b/block/backup-top.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/block/backup-top.c
47
+++ b/block/backup-top.c
48
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
49
*nperm = BLK_PERM_WRITE;
50
} else {
51
/* Source child */
52
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
53
- perm, shared, nperm, nshared);
54
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
55
+ perm, shared, nperm, nshared);
56
57
if (perm & BLK_PERM_WRITE) {
58
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
59
diff --git a/block/blkdebug.c b/block/blkdebug.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/block/blkdebug.c
62
+++ b/block/blkdebug.c
63
@@ -XXX,XX +XXX,XX @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
64
{
65
BDRVBlkdebugState *s = bs->opaque;
66
67
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
68
- perm, shared, nperm, nshared);
69
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
70
+ perm, shared, nperm, nshared);
71
72
*nperm |= s->take_child_perms;
73
*nshared &= ~s->unshare_child_perms;
74
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/blklogwrites.c
77
+++ b/block/blklogwrites.c
78
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
79
return;
80
}
81
82
- if (!strcmp(c->name, "log")) {
83
- bdrv_format_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
84
- nperm, nshrd);
85
- } else {
86
- bdrv_filter_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
87
- nperm, nshrd);
88
- }
89
+ bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
90
+ nperm, nshrd);
23
}
91
}
24
92
25
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
93
static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
26
+{
94
diff --git a/block/blkreplay.c b/block/blkreplay.c
27
+ /* The generic bdrv_dirname() implementation is able to work out some
95
index XXXXXXX..XXXXXXX 100644
28
+ * directory name for NBD nodes, but that would be wrong. So far there is no
96
--- a/block/blkreplay.c
29
+ * specification for how "export paths" would work, so NBD does not have
97
+++ b/block/blkreplay.c
30
+ * directory names. */
98
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkreplay = {
31
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
99
.is_filter = true,
32
+ return NULL;
100
33
+}
101
.bdrv_open = blkreplay_open,
34
+
102
- .bdrv_child_perm = bdrv_filter_default_perms,
35
static BlockDriver bdrv_nbd = {
103
+ .bdrv_child_perm = bdrv_default_perms,
36
.format_name = "nbd",
104
.bdrv_getlength = blkreplay_getlength,
37
.protocol_name = "nbd",
105
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
106
.bdrv_co_preadv = blkreplay_co_preadv,
39
.bdrv_attach_aio_context = nbd_attach_aio_context,
107
diff --git a/block/blkverify.c b/block/blkverify.c
40
.bdrv_refresh_filename = nbd_refresh_filename,
108
index XXXXXXX..XXXXXXX 100644
41
.bdrv_co_block_status = nbd_client_co_block_status,
109
--- a/block/blkverify.c
42
+ .bdrv_dirname = nbd_dirname,
110
+++ b/block/blkverify.c
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
112
.bdrv_parse_filename = blkverify_parse_filename,
113
.bdrv_file_open = blkverify_open,
114
.bdrv_close = blkverify_close,
115
- .bdrv_child_perm = bdrv_filter_default_perms,
116
+ .bdrv_child_perm = bdrv_default_perms,
117
.bdrv_getlength = blkverify_getlength,
118
.bdrv_refresh_filename = blkverify_refresh_filename,
119
.bdrv_dirname = blkverify_dirname,
120
diff --git a/block/bochs.c b/block/bochs.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/bochs.c
123
+++ b/block/bochs.c
124
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_bochs = {
125
.instance_size    = sizeof(BDRVBochsState),
126
.bdrv_probe        = bochs_probe,
127
.bdrv_open        = bochs_open,
128
- .bdrv_child_perm = bdrv_format_default_perms,
129
+ .bdrv_child_perm = bdrv_default_perms,
130
.bdrv_refresh_limits = bochs_refresh_limits,
131
.bdrv_co_preadv = bochs_co_preadv,
132
.bdrv_close        = bochs_close,
133
diff --git a/block/cloop.c b/block/cloop.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/block/cloop.c
136
+++ b/block/cloop.c
137
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_cloop = {
138
.instance_size = sizeof(BDRVCloopState),
139
.bdrv_probe = cloop_probe,
140
.bdrv_open = cloop_open,
141
- .bdrv_child_perm = bdrv_format_default_perms,
142
+ .bdrv_child_perm = bdrv_default_perms,
143
.bdrv_refresh_limits = cloop_refresh_limits,
144
.bdrv_co_preadv = cloop_co_preadv,
145
.bdrv_close = cloop_close,
146
diff --git a/block/crypto.c b/block/crypto.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/crypto.c
149
+++ b/block/crypto.c
150
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_crypto_luks = {
151
.bdrv_close = block_crypto_close,
152
/* This driver doesn't modify LUKS metadata except when creating image.
153
* Allow share-rw=on as a special case. */
154
- .bdrv_child_perm = bdrv_filter_default_perms,
155
+ .bdrv_child_perm = bdrv_default_perms,
156
.bdrv_co_create = block_crypto_co_create_luks,
157
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
158
.bdrv_co_truncate = block_crypto_co_truncate,
159
diff --git a/block/dmg.c b/block/dmg.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/dmg.c
162
+++ b/block/dmg.c
163
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_dmg = {
164
.bdrv_probe = dmg_probe,
165
.bdrv_open = dmg_open,
166
.bdrv_refresh_limits = dmg_refresh_limits,
167
- .bdrv_child_perm = bdrv_format_default_perms,
168
+ .bdrv_child_perm = bdrv_default_perms,
169
.bdrv_co_preadv = dmg_co_preadv,
170
.bdrv_close = dmg_close,
171
.is_format = true,
172
diff --git a/block/filter-compress.c b/block/filter-compress.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/filter-compress.c
175
+++ b/block/filter-compress.c
176
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_compress = {
177
.format_name = "compress",
178
179
.bdrv_open = compress_open,
180
- .bdrv_child_perm = bdrv_filter_default_perms,
181
+ .bdrv_child_perm = bdrv_default_perms,
182
183
.bdrv_getlength = compress_getlength,
184
185
diff --git a/block/parallels.c b/block/parallels.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/block/parallels.c
188
+++ b/block/parallels.c
189
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
190
.bdrv_probe        = parallels_probe,
191
.bdrv_open        = parallels_open,
192
.bdrv_close        = parallels_close,
193
- .bdrv_child_perm = bdrv_format_default_perms,
194
+ .bdrv_child_perm = bdrv_default_perms,
195
.bdrv_co_block_status = parallels_co_block_status,
196
.bdrv_has_zero_init = bdrv_has_zero_init_1,
197
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
198
diff --git a/block/qcow.c b/block/qcow.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/qcow.c
201
+++ b/block/qcow.c
202
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
203
.bdrv_probe        = qcow_probe,
204
.bdrv_open        = qcow_open,
205
.bdrv_close        = qcow_close,
206
- .bdrv_child_perm = bdrv_format_default_perms,
207
+ .bdrv_child_perm = bdrv_default_perms,
208
.bdrv_reopen_prepare = qcow_reopen_prepare,
209
.bdrv_co_create = qcow_co_create,
210
.bdrv_co_create_opts = qcow_co_create_opts,
211
diff --git a/block/qcow2.c b/block/qcow2.c
212
index XXXXXXX..XXXXXXX 100644
213
--- a/block/qcow2.c
214
+++ b/block/qcow2.c
215
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
216
.bdrv_reopen_commit_post = qcow2_reopen_commit_post,
217
.bdrv_reopen_abort = qcow2_reopen_abort,
218
.bdrv_join_options = qcow2_join_options,
219
- .bdrv_child_perm = bdrv_format_default_perms,
220
+ .bdrv_child_perm = bdrv_default_perms,
221
.bdrv_co_create_opts = qcow2_co_create_opts,
222
.bdrv_co_create = qcow2_co_create,
223
.bdrv_has_zero_init = qcow2_has_zero_init,
224
diff --git a/block/qed.c b/block/qed.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/block/qed.c
227
+++ b/block/qed.c
228
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
229
.bdrv_open = bdrv_qed_open,
230
.bdrv_close = bdrv_qed_close,
231
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
232
- .bdrv_child_perm = bdrv_format_default_perms,
233
+ .bdrv_child_perm = bdrv_default_perms,
234
.bdrv_co_create = bdrv_qed_co_create,
235
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
236
.bdrv_has_zero_init = bdrv_has_zero_init_1,
237
diff --git a/block/raw-format.c b/block/raw-format.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/raw-format.c
240
+++ b/block/raw-format.c
241
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
242
.bdrv_reopen_commit = &raw_reopen_commit,
243
.bdrv_reopen_abort = &raw_reopen_abort,
244
.bdrv_open = &raw_open,
245
- .bdrv_child_perm = bdrv_filter_default_perms,
246
+ .bdrv_child_perm = bdrv_default_perms,
247
.bdrv_co_create_opts = &raw_co_create_opts,
248
.bdrv_co_preadv = &raw_co_preadv,
249
.bdrv_co_pwritev = &raw_co_pwritev,
250
diff --git a/block/throttle.c b/block/throttle.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/block/throttle.c
253
+++ b/block/throttle.c
254
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
255
.bdrv_close = throttle_close,
256
.bdrv_co_flush = throttle_co_flush,
257
258
- .bdrv_child_perm = bdrv_filter_default_perms,
259
+ .bdrv_child_perm = bdrv_default_perms,
260
261
.bdrv_getlength = throttle_getlength,
262
263
diff --git a/block/vdi.c b/block/vdi.c
264
index XXXXXXX..XXXXXXX 100644
265
--- a/block/vdi.c
266
+++ b/block/vdi.c
267
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
268
.bdrv_open = vdi_open,
269
.bdrv_close = vdi_close,
270
.bdrv_reopen_prepare = vdi_reopen_prepare,
271
- .bdrv_child_perm = bdrv_format_default_perms,
272
+ .bdrv_child_perm = bdrv_default_perms,
273
.bdrv_co_create = vdi_co_create,
274
.bdrv_co_create_opts = vdi_co_create_opts,
275
.bdrv_has_zero_init = vdi_has_zero_init,
276
diff --git a/block/vhdx.c b/block/vhdx.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/vhdx.c
279
+++ b/block/vhdx.c
280
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
281
.bdrv_open = vhdx_open,
282
.bdrv_close = vhdx_close,
283
.bdrv_reopen_prepare = vhdx_reopen_prepare,
284
- .bdrv_child_perm = bdrv_format_default_perms,
285
+ .bdrv_child_perm = bdrv_default_perms,
286
.bdrv_co_readv = vhdx_co_readv,
287
.bdrv_co_writev = vhdx_co_writev,
288
.bdrv_co_create = vhdx_co_create,
289
diff --git a/block/vmdk.c b/block/vmdk.c
290
index XXXXXXX..XXXXXXX 100644
291
--- a/block/vmdk.c
292
+++ b/block/vmdk.c
293
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
294
.bdrv_open = vmdk_open,
295
.bdrv_co_check = vmdk_co_check,
296
.bdrv_reopen_prepare = vmdk_reopen_prepare,
297
- .bdrv_child_perm = bdrv_format_default_perms,
298
+ .bdrv_child_perm = bdrv_default_perms,
299
.bdrv_co_preadv = vmdk_co_preadv,
300
.bdrv_co_pwritev = vmdk_co_pwritev,
301
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
302
diff --git a/block/vpc.c b/block/vpc.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/block/vpc.c
305
+++ b/block/vpc.c
306
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
307
.bdrv_open = vpc_open,
308
.bdrv_close = vpc_close,
309
.bdrv_reopen_prepare = vpc_reopen_prepare,
310
- .bdrv_child_perm = bdrv_format_default_perms,
311
+ .bdrv_child_perm = bdrv_default_perms,
312
.bdrv_co_create = vpc_co_create,
313
.bdrv_co_create_opts = vpc_co_create_opts,
314
315
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/tests/test-bdrv-drain.c
318
+++ b/tests/test-bdrv-drain.c
319
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
320
uint64_t *nperm, uint64_t *nshared)
321
{
322
/*
323
- * bdrv_format_default_perms() accepts only these two, so disguise
324
+ * bdrv_default_perms() accepts only these two, so disguise
325
* detach_by_driver_cb_parent as one of them.
326
*/
327
if (child_class != &child_file && child_class != &child_of_bds) {
328
child_class = &child_of_bds;
329
}
330
331
- bdrv_format_default_perms(bs, c, child_class, role, reopen_queue,
332
- perm, shared, nperm, nshared);
333
+ bdrv_default_perms(bs, c, child_class, role, reopen_queue,
334
+ perm, shared, nperm, nshared);
335
}
336
337
static int bdrv_test_change_backing_file(BlockDriverState *bs,
338
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_test_top_driver = {
339
.bdrv_close = bdrv_test_top_close,
340
.bdrv_co_preadv = bdrv_test_top_co_preadv,
341
342
- .bdrv_child_perm = bdrv_format_default_perms,
343
+ .bdrv_child_perm = bdrv_default_perms,
43
};
344
};
44
345
45
static BlockDriver bdrv_nbd_tcp = {
346
typedef struct TestCoDeleteByDrainData {
46
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
347
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_replace_test = {
47
.bdrv_attach_aio_context = nbd_attach_aio_context,
348
.bdrv_co_drain_begin = bdrv_replace_test_co_drain_begin,
48
.bdrv_refresh_filename = nbd_refresh_filename,
349
.bdrv_co_drain_end = bdrv_replace_test_co_drain_end,
49
.bdrv_co_block_status = nbd_client_co_block_status,
350
50
+ .bdrv_dirname = nbd_dirname,
351
- .bdrv_child_perm = bdrv_format_default_perms,
352
+ .bdrv_child_perm = bdrv_default_perms,
51
};
353
};
52
354
53
static BlockDriver bdrv_nbd_unix = {
355
static void coroutine_fn test_replace_child_mid_drain_read_co(void *opaque)
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
356
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
55
.bdrv_attach_aio_context = nbd_attach_aio_context,
357
index XXXXXXX..XXXXXXX 100644
56
.bdrv_refresh_filename = nbd_refresh_filename,
358
--- a/tests/test-bdrv-graph-mod.c
57
.bdrv_co_block_status = nbd_client_co_block_status,
359
+++ b/tests/test-bdrv-graph-mod.c
58
+ .bdrv_dirname = nbd_dirname,
360
@@ -XXX,XX +XXX,XX @@
361
362
static BlockDriver bdrv_pass_through = {
363
.format_name = "pass-through",
364
- .bdrv_child_perm = bdrv_filter_default_perms,
365
+ .bdrv_child_perm = bdrv_default_perms,
59
};
366
};
60
367
61
static void bdrv_nbd_init(void)
368
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
369
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/tests/test-block-iothread.c
372
+++ b/tests/test-block-iothread.c
373
@@ -XXX,XX +XXX,XX @@ static void test_propagate_basic(void)
374
BlockDriverState *bs_a, *bs_b, *bs_verify;
375
QDict *options;
376
377
- /* Create bs_a and its BlockBackend */
378
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
379
+ /*
380
+ * Create bs_a and its BlockBackend. We cannot take the RESIZE
381
+ * permission because blkverify will not share it on the test
382
+ * image.
383
+ */
384
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
385
+ BLK_PERM_ALL);
386
bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
387
blk_insert_bs(blk, bs_a, &error_abort);
388
389
@@ -XXX,XX +XXX,XX @@ static void test_propagate_diamond(void)
390
qdict_put_str(options, "raw", "bs_c");
391
392
bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
393
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
394
+ /*
395
+ * Do not take the RESIZE permission: This would require the same
396
+ * from bs_c and thus from bs_a; however, blkverify will not share
397
+ * it on bs_b, and thus it will not be available for bs_a.
398
+ */
399
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
400
+ BLK_PERM_ALL);
401
blk_insert_bs(blk, bs_verify, &error_abort);
402
403
/* Switch the AioContext */
62
--
404
--
63
2.20.1
405
2.25.4
64
406
65
407
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Message-id: 20190201192935.18394-29-mreitz@redhat.com
5
Message-Id: <20200513110544.176672-31-mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
7
---
8
block/curl.c | 21 +++++++++++++++++++++
8
include/block/block_int.h | 10 ----------
9
1 file changed, 21 insertions(+)
9
block.c | 17 +++++++++++------
10
2 files changed, 11 insertions(+), 16 deletions(-)
10
11
11
diff --git a/block/curl.c b/block/curl.c
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/block/curl.c
14
--- a/include/block/block_int.h
14
+++ b/block/curl.c
15
+++ b/include/block/block_int.h
15
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
16
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
16
return s->len;
17
*/
18
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
19
20
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
21
- * block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to
22
- * all children */
23
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
24
- const BdrvChildClass *child_class,
25
- BdrvChildRole child_role,
26
- BlockReopenQueue *reopen_queue,
27
- uint64_t perm, uint64_t shared,
28
- uint64_t *nperm, uint64_t *nshared);
29
-
30
/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
31
* (non-raw) image formats: Like above for bs->backing, but for bs->file it
32
* requires WRITE | RESIZE for read-write images, always requires
33
diff --git a/block.c b/block.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/block.c
36
+++ b/block.c
37
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
38
return bdrv_child_try_set_perm(c, perms, shared, errp);
17
}
39
}
18
40
19
+static void curl_refresh_filename(BlockDriverState *bs)
41
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
20
+{
42
- const BdrvChildClass *child_class,
21
+ BDRVCURLState *s = bs->opaque;
43
- BdrvChildRole role,
22
+
44
- BlockReopenQueue *reopen_queue,
23
+ /* "readahead" and "timeout" do not change the guest-visible data,
45
- uint64_t perm, uint64_t shared,
24
+ * so ignore them */
46
- uint64_t *nperm, uint64_t *nshared)
25
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
47
+/*
26
+ s->cookie || s->username || s->password || s->proxyusername ||
48
+ * Default implementation for .bdrv_child_perm() for block filters:
27
+ s->proxypassword)
49
+ * Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED, and RESIZE to the
28
+ {
50
+ * filtered child.
29
+ return;
51
+ */
30
+ }
52
+static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
31
+
53
+ const BdrvChildClass *child_class,
32
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
54
+ BdrvChildRole role,
33
+}
55
+ BlockReopenQueue *reopen_queue,
34
+
56
+ uint64_t perm, uint64_t shared,
35
+
57
+ uint64_t *nperm, uint64_t *nshared)
36
static const char *const curl_strong_runtime_opts[] = {
58
{
37
CURL_BLOCK_OPT_URL,
59
*nperm = perm & DEFAULT_PERM_PASSTHROUGH;
38
CURL_BLOCK_OPT_SSLVERIFY,
60
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
40
.bdrv_detach_aio_context = curl_detach_aio_context,
41
.bdrv_attach_aio_context = curl_attach_aio_context,
42
43
+ .bdrv_refresh_filename = curl_refresh_filename,
44
.strong_runtime_opts = curl_strong_runtime_opts,
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
48
.bdrv_detach_aio_context = curl_detach_aio_context,
49
.bdrv_attach_aio_context = curl_attach_aio_context,
50
51
+ .bdrv_refresh_filename = curl_refresh_filename,
52
.strong_runtime_opts = curl_strong_runtime_opts,
53
};
54
55
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
56
.bdrv_detach_aio_context = curl_detach_aio_context,
57
.bdrv_attach_aio_context = curl_attach_aio_context,
58
59
+ .bdrv_refresh_filename = curl_refresh_filename,
60
.strong_runtime_opts = curl_strong_runtime_opts,
61
};
62
63
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
64
.bdrv_detach_aio_context = curl_detach_aio_context,
65
.bdrv_attach_aio_context = curl_attach_aio_context,
66
67
+ .bdrv_refresh_filename = curl_refresh_filename,
68
.strong_runtime_opts = curl_strong_runtime_opts,
69
};
70
71
--
61
--
72
2.20.1
62
2.25.4
73
63
74
64
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
After the previous patch, the only instance of this function left
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
is inside qemu-img.c.
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
5
Message-Id: <20200513110544.176672-32-mreitz@redhat.com>
6
qemu-img is using it inside the 'img_snapshot' function to delete
7
snapshots in the SNAPSHOT_DELETE case, based on a "snapshot_name"
8
string that refers to the tag, not ID, of the QEMUSnapshotInfo struct.
9
This can be verified by checking the SNAPSHOT_CREATE case that
10
comes shortly before SNAPSHOT_DELETE. In that case, the same
11
"snapshot_name" variable is being strcpy to the 'name' field
12
of the QEMUSnapshotInfo struct sn:
13
14
pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
15
16
Based on that, it is unlikely that "snapshot_name" might contain
17
an "id" in SNAPSHOT_DELETE.
18
19
This patch changes SNAPSHOT_DELETE to use snapshot_find() and
20
snapshot_delete() instead of bdrv_snapshot_delete_by_id_or_name.
21
After that, there is no instances left of bdrv_snapshot_delete_by_id_or_name
22
in the code, so it is safe to remove it entirely.
23
24
Suggested-by: Murilo Opsfelder Araujo <muriloo@linux.ibm.com>
25
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
7
---
28
include/block/snapshot.h | 3 ---
8
include/block/block_int.h | 11 -----------
29
block/snapshot.c | 20 --------------------
9
block.c | 19 -------------------
30
qemu-img.c | 15 +++++++++++----
10
2 files changed, 30 deletions(-)
31
3 files changed, 11 insertions(+), 27 deletions(-)
32
11
33
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
12
diff --git a/include/block/block_int.h b/include/block/block_int.h
34
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/snapshot.h
14
--- a/include/block/block_int.h
36
+++ b/include/block/snapshot.h
15
+++ b/include/block/block_int.h
37
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
16
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
38
const char *snapshot_id,
17
*/
39
const char *name,
18
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
40
Error **errp);
19
41
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
20
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
42
- const char *id_or_name,
21
- * (non-raw) image formats: Like above for bs->backing, but for bs->file it
43
- Error **errp);
22
- * requires WRITE | RESIZE for read-write images, always requires
44
int bdrv_snapshot_list(BlockDriverState *bs,
23
- * CONSISTENT_READ and doesn't share WRITE. */
45
QEMUSnapshotInfo **psn_info);
24
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
46
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
25
- const BdrvChildClass *child_class,
47
diff --git a/block/snapshot.c b/block/snapshot.c
26
- BdrvChildRole child_role,
27
- BlockReopenQueue *reopen_queue,
28
- uint64_t perm, uint64_t shared,
29
- uint64_t *nperm, uint64_t *nshared);
30
-
31
bool bdrv_recurse_can_replace(BlockDriverState *bs,
32
BlockDriverState *to_replace);
33
34
diff --git a/block.c b/block.c
48
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
49
--- a/block/snapshot.c
36
--- a/block.c
50
+++ b/block/snapshot.c
37
+++ b/block.c
51
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
38
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
52
return ret;
39
*nshared = shared;
53
}
40
}
54
41
55
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
42
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
56
- const char *id_or_name,
43
- const BdrvChildClass *child_class,
57
- Error **errp)
44
- BdrvChildRole role,
45
- BlockReopenQueue *reopen_queue,
46
- uint64_t perm, uint64_t shared,
47
- uint64_t *nperm, uint64_t *nshared)
58
-{
48
-{
59
- int ret;
49
- if (child_class == &child_of_bds) {
60
- Error *local_err = NULL;
50
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
61
-
51
- perm, shared, nperm, nshared);
62
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
52
- return;
63
- if (ret == -ENOENT || ret == -EINVAL) {
64
- error_free(local_err);
65
- local_err = NULL;
66
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
67
- }
53
- }
68
-
54
-
69
- if (ret < 0) {
55
- assert(child_class == &child_file);
70
- error_propagate(errp, local_err);
56
-
71
- }
57
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
72
- return ret;
58
- perm, shared, nperm, nshared);
73
-}
59
-}
74
-
60
-
75
int bdrv_snapshot_list(BlockDriverState *bs,
61
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
76
QEMUSnapshotInfo **psn_info)
62
const BdrvChildClass *child_class, BdrvChildRole role,
77
{
63
BlockReopenQueue *reopen_queue,
78
diff --git a/qemu-img.c b/qemu-img.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/qemu-img.c
81
+++ b/qemu-img.c
82
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
83
break;
84
85
case SNAPSHOT_DELETE:
86
- bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
87
- if (err) {
88
- error_reportf_err(err, "Could not delete snapshot '%s': ",
89
- snapshot_name);
90
+ ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
91
+ if (ret < 0) {
92
+ error_report("Could not delete snapshot '%s': snapshot not "
93
+ "found", snapshot_name);
94
ret = 1;
95
+ } else {
96
+ ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
97
+ if (ret < 0) {
98
+ error_reportf_err(err, "Could not delete snapshot '%s': ",
99
+ snapshot_name);
100
+ ret = 1;
101
+ }
102
}
103
break;
104
}
105
--
64
--
106
2.20.1
65
2.25.4
107
66
108
67
diff view generated by jsdifflib
Deleted patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
1
3
In qcow2_snapshot_create there is the following code block:
4
5
/* Generate an ID */
6
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
7
8
/* Check that the ID is unique */
9
if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
10
return -EEXIST;
11
}
12
13
find_new_snapshot_id cycles through all snapshots, getting the id_str
14
as an unsigned long int, calculating the max id_max value of all the
15
existing id_strs and writing in the id_str pointer id_max + 1:
16
17
for(i = 0; i < s->nb_snapshots; i++) {
18
sn = s->snapshots + i;
19
id = strtoul(sn->id_str, NULL, 10);
20
if (id > id_max)
21
id_max = id;
22
}
23
snprintf(id_str, id_str_size, "%lu", id_max + 1);
24
25
Here, sn_info->id_str will have the unique value id_max + 1. Right
26
after that, find_snapshot_by_id_and_name is called with
27
id = sn_info->id_str and name = NULL. This will cause the function
28
to execute the following:
29
30
} else if (id) {
31
for (i = 0; i < s->nb_snapshots; i++) {
32
if (!strcmp(s->snapshots[i].id_str, id)) {
33
return i;
34
}
35
}
36
}
37
38
In short, we're searching the existing snapshots to see if sn_info->id_str
39
matches any existing id, right after we set in the previous line a
40
sn_info->id_str value that is already unique.
41
42
The first code block goes way back to commit 585f8587ad, a 2006 commit from
43
Fabrice Bellard that simply says "new qcow2 disk image format". No more
44
info is provided about this logic in any subsequent commits that moved
45
this code block around.
46
47
I can't say about the original design, but the current logic is redundant.
48
bdrv_snapshot_create is called in aio_context lock, forbidding any
49
concurrent call to accidentally create a new snapshot between
50
the find_new_snapshot_id and find_snapshot_by_id_and_name calls. What
51
we're ending up doing is to cycle through the snapshots two times
52
for no viable reason.
53
54
This patch eliminates the redundancy by removing the 'id is unique'
55
check that calls find_snapshot_by_id_and_name.
56
57
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
58
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
59
---
60
block/qcow2-snapshot.c | 5 -----
61
1 file changed, 5 deletions(-)
62
63
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/qcow2-snapshot.c
66
+++ b/block/qcow2-snapshot.c
67
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
68
/* Generate an ID */
69
find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
70
71
- /* Check that the ID is unique */
72
- if (find_snapshot_by_id_and_name(bs, sn_info->id_str, NULL) >= 0) {
73
- return -EEXIST;
74
- }
75
-
76
/* Populate sn with passed data */
77
sn->id_str = g_strdup(sn_info->id_str);
78
sn->name = g_strdup(sn_info->name);
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-7-mreitz@redhat.com
4
Message-Id: <20200513110544.176672-33-mreitz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
7
---
8
tests/qemu-iotests/iotests.py | 10 ++++++++++
8
include/block/block_int.h | 1 -
9
1 file changed, 10 insertions(+)
9
block.c | 39 ++-------------------------------------
10
tests/test-bdrv-drain.c | 8 +++-----
11
3 files changed, 5 insertions(+), 43 deletions(-)
10
12
11
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
13
diff --git a/include/block/block_int.h b/include/block/block_int.h
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/iotests.py
15
--- a/include/block/block_int.h
14
+++ b/tests/qemu-iotests/iotests.py
16
+++ b/include/block/block_int.h
15
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
17
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
16
lines.append(line)
18
};
17
return '\n'.join(lines)
19
18
20
extern const BdrvChildClass child_of_bds;
19
+def filter_imgfmt(msg):
21
-extern const BdrvChildClass child_file;
20
+ return msg.replace(imgfmt, 'IMGFMT')
22
21
+
23
struct BdrvChild {
22
+def filter_qmp_imgfmt(qmsg):
24
BlockDriverState *bs;
23
+ def _filter(key, value):
25
diff --git a/block.c b/block.c
24
+ if is_str(value):
26
index XXXXXXX..XXXXXXX 100644
25
+ return filter_imgfmt(value)
27
--- a/block.c
26
+ return value
28
+++ b/block.c
27
+ return filter_qmp(qmsg, _filter)
29
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
28
+
30
BdrvChildRole child_role,
29
def log(msg, filters=[], indent=None):
31
Error **errp);
30
'''Logs either a string message or a JSON serializable message (like QMP).
32
31
If indent is provided, JSON serializable messages are pretty-printed.'''
33
-/* TODO: Remove when no longer needed */
34
-static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
35
- int *child_flags, QDict *child_options,
36
- int parent_flags, QDict *parent_options);
37
-static void bdrv_child_cb_attach(BdrvChild *child);
38
-static void bdrv_child_cb_detach(BdrvChild *child);
39
-
40
/* If non-zero, use only whitelisted block drivers */
41
static int use_bdrv_whitelist;
42
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
44
*child_flags &= ~BDRV_O_NATIVE_AIO;
45
}
46
47
-/*
48
- * Returns the options and flags that bs->file should get if a protocol driver
49
- * is expected, based on the given options and flags for the parent BDS
50
- */
51
-static void bdrv_protocol_options(BdrvChildRole role, bool parent_is_format,
52
- int *child_flags, QDict *child_options,
53
- int parent_flags, QDict *parent_options)
54
-{
55
- bdrv_inherited_options(BDRV_CHILD_IMAGE, true,
56
- child_flags, child_options,
57
- parent_flags, parent_options);
58
-}
59
-
60
-const BdrvChildClass child_file = {
61
- .parent_is_bds = true,
62
- .get_parent_desc = bdrv_child_get_parent_desc,
63
- .inherit_options = bdrv_protocol_options,
64
- .drained_begin = bdrv_child_cb_drained_begin,
65
- .drained_poll = bdrv_child_cb_drained_poll,
66
- .drained_end = bdrv_child_cb_drained_end,
67
- .attach = bdrv_child_cb_attach,
68
- .detach = bdrv_child_cb_detach,
69
- .inactivate = bdrv_child_cb_inactivate,
70
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
71
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
72
-};
73
-
74
static void bdrv_backing_attach(BdrvChild *c)
75
{
76
BlockDriverState *parent = c->opaque;
77
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
78
{
79
int flags;
80
81
- assert(child_class == &child_file ||
82
- (child_class == &child_of_bds &&
83
- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA))));
84
+ assert(child_class == &child_of_bds &&
85
+ (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)));
86
87
flags = bdrv_reopen_get_flags(reopen_queue, bs);
88
89
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/tests/test-bdrv-drain.c
92
+++ b/tests/test-bdrv-drain.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
94
uint64_t *nperm, uint64_t *nshared)
95
{
96
/*
97
- * bdrv_default_perms() accepts only these two, so disguise
98
- * detach_by_driver_cb_parent as one of them.
99
+ * bdrv_default_perms() accepts nothing else, so disguise
100
+ * detach_by_driver_cb_parent.
101
*/
102
- if (child_class != &child_file && child_class != &child_of_bds) {
103
- child_class = &child_of_bds;
104
- }
105
+ child_class = &child_of_bds;
106
107
bdrv_default_perms(bs, c, child_class, role, reopen_queue,
108
perm, shared, nperm, nshared);
32
--
109
--
33
2.20.1
110
2.25.4
34
111
35
112
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This follows what qmp() does, so the output will correspond to the
3
These calls have no real use for the child role yet, but it will not
4
actual QMP command.
4
harm to give one.
5
6
Notably, the bdrv_root_attach_child() call in blockjob.c is left
7
unmodified because there is not much the generic BlockJob object wants
8
from its children.
5
9
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190210145736.1486-11-mreitz@redhat.com
11
Message-Id: <20200513110544.176672-34-mreitz@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
14
---
10
tests/qemu-iotests/206.out | 56 +++++++++++++++++------------------
15
block/block-backend.c | 11 +++++++----
11
tests/qemu-iotests/207.out | 18 +++++------
16
block/vvfat.c | 4 +++-
12
tests/qemu-iotests/210.out | 28 +++++++++---------
17
2 files changed, 10 insertions(+), 5 deletions(-)
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
18
20
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
19
diff --git a/block/block-backend.c b/block/block-backend.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/206.out
21
--- a/block/block-backend.c
23
+++ b/tests/qemu-iotests/206.out
22
+++ b/block/block-backend.c
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
25
=== Successful image creation (defaults) ===
24
return NULL;
26
25
}
27
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
26
28
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
27
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
29
{"return": {}}
28
- perm, BLK_PERM_ALL, blk, errp);
30
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
29
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
31
{"return": {}}
30
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
32
31
+ blk->ctx, perm, BLK_PERM_ALL, blk, errp);
33
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
32
if (!blk->root) {
34
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
33
blk_unref(blk);
35
{"return": {}}
34
return NULL;
36
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
35
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
37
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
36
{
38
{"return": {}}
37
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
39
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
38
bdrv_ref(bs);
40
{"return": {}}
39
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, 0, blk->ctx,
41
@@ -XXX,XX +XXX,XX @@ Format specific information:
40
- blk->perm, blk->shared_perm, blk, errp);
42
41
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
43
=== Successful image creation (inline blockdev-add, explicit defaults) ===
42
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
44
43
+ blk->ctx, blk->perm, blk->shared_perm,
45
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
44
+ blk, errp);
46
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
45
if (blk->root == NULL) {
47
{"return": {}}
46
return -EPERM;
48
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
47
}
49
{"return": {}}
48
diff --git a/block/vvfat.c b/block/vvfat.c
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
49
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/qemu-iotests/207.out
50
--- a/block/vvfat.c
228
+++ b/tests/qemu-iotests/207.out
51
+++ b/block/vvfat.c
229
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
230
=== Successful image creation (defaults) ===
53
options = qdict_new();
231
54
qdict_put_str(options, "write-target.driver", "qcow");
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}}}
55
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
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}}}
56
- &child_vvfat_qcow, 0, false, errp);
234
{"return": {}}
57
+ &child_vvfat_qcow,
235
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
58
+ BDRV_CHILD_DATA | BDRV_CHILD_METADATA,
236
{"return": {}}
59
+ false, errp);
237
@@ -XXX,XX +XXX,XX @@ virtual size: 4.0M (4194304 bytes)
60
qobject_unref(options);
238
61
if (!s->qcow) {
239
=== Test host-key-check options ===
62
ret = -EINVAL;
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
--
63
--
1069
2.20.1
64
2.25.4
1070
65
1071
66
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Some follow-up patches will rework the way bs->full_open_options is
3
Implementations should decide the necessary permissions based on @role.
4
refreshed in bdrv_refresh_filename(). The new implementation will remove
5
the need for the block drivers' bdrv_refresh_filename() implementations
6
to set bs->full_open_options; instead, it will be generic and use static
7
information from each block driver.
8
9
However, by implementing bdrv_gather_child_options(), block drivers will
10
still be able to override the way the full_open_options of their
11
children are incorporated into their own.
12
13
We need to implement this function for VMDK because we have to prevent
14
the generic implementation from gathering the options of all children:
15
It is not possible to specify options for the extents through the
16
runtime options.
17
18
For quorum, the child names that would be used by the generic
19
implementation and the ones that we actually (currently) want to use
20
differ. See quorum_gather_child_options() for more information.
21
22
Note that both of these are cases which are not ideal: In case of VMDK
23
it would probably be nice to be able to specify options for all extents.
24
In case of quorum, the current runtime option structure is simply broken
25
and needs to be fixed (but that is left for another patch).
26
4
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Message-Id: <20200513110544.176672-35-mreitz@redhat.com>
29
Message-id: 20190201192935.18394-23-mreitz@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
30
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
---
9
---
32
include/block/block_int.h | 24 +++++++++++++++++++++++
10
include/block/block_int.h | 4 +---
33
block/quorum.c | 40 +++++++++++++++++++++++++++++++++++++++
11
block.c | 39 +++++++++++++++----------------------
34
block/vmdk.c | 19 +++++++++++++++++++
12
block/backup-top.c | 3 +--
35
3 files changed, 83 insertions(+)
13
block/blkdebug.c | 3 +--
14
block/blklogwrites.c | 3 +--
15
block/commit.c | 1 -
16
block/copy-on-read.c | 1 -
17
block/mirror.c | 1 -
18
block/quorum.c | 1 -
19
block/replication.c | 1 -
20
block/vvfat.c | 4 +---
21
tests/test-bdrv-drain.c | 19 +-----------------
22
tests/test-bdrv-graph-mod.c | 1 -
23
13 files changed, 22 insertions(+), 59 deletions(-)
36
24
37
diff --git a/include/block/block_int.h b/include/block/block_int.h
25
diff --git a/include/block/block_int.h b/include/block/block_int.h
38
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block_int.h
27
--- a/include/block/block_int.h
40
+++ b/include/block/block_int.h
28
+++ b/include/block/block_int.h
41
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
42
30
* @reopen_queue.
43
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
31
*/
44
32
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
45
+ /*
33
- const BdrvChildClass *child_class,
46
+ * Gathers the open options for all children into @target.
34
BdrvChildRole role,
47
+ * A simple format driver (without backing file support) might
35
BlockReopenQueue *reopen_queue,
48
+ * implement this function like this:
36
uint64_t parent_perm, uint64_t parent_shared,
49
+ *
37
@@ -XXX,XX +XXX,XX @@ bool bdrv_recurse_can_replace(BlockDriverState *bs,
50
+ * QINCREF(bs->file->bs->full_open_options);
38
* child_of_bds child class and set an appropriate BdrvChildRole.
51
+ * qdict_put(target, "file", bs->file->bs->full_open_options);
39
*/
52
+ *
40
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
53
+ * If not specified, the generic implementation will simply put
41
- const BdrvChildClass *child_class, BdrvChildRole role,
54
+ * all children's options under their respective name.
42
- BlockReopenQueue *reopen_queue,
55
+ *
43
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
56
+ * @backing_overridden is true when bs->backing seems not to be
44
uint64_t perm, uint64_t shared,
57
+ * the child that would result from opening bs->backing_file.
45
uint64_t *nperm, uint64_t *nshared);
58
+ * Therefore, if it is true, the backing child's options should be
46
59
+ * gathered; otherwise, there is no need since the backing child
47
diff --git a/block.c b/block.c
60
+ * is the one implied by the image header.
48
index XXXXXXX..XXXXXXX 100644
61
+ *
49
--- a/block.c
62
+ * Note that ideally this function would not be needed. Every
50
+++ b/block.c
63
+ * block driver which implements it is probably doing something
51
@@ -XXX,XX +XXX,XX @@ bool bdrv_is_writable(BlockDriverState *bs)
64
+ * shady regarding its runtime option structure.
52
}
65
+ */
53
66
+ void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
54
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
67
+ bool backing_overridden);
55
- BdrvChild *c, const BdrvChildClass *child_class,
68
+
56
- BdrvChildRole role, BlockReopenQueue *reopen_queue,
57
+ BdrvChild *c, BdrvChildRole role,
58
+ BlockReopenQueue *reopen_queue,
59
uint64_t parent_perm, uint64_t parent_shared,
60
uint64_t *nperm, uint64_t *nshared)
61
{
62
assert(bs->drv && bs->drv->bdrv_child_perm);
63
- bs->drv->bdrv_child_perm(bs, c, child_class, role, reopen_queue,
64
+ bs->drv->bdrv_child_perm(bs, c, role, reopen_queue,
65
parent_perm, parent_shared,
66
nperm, nshared);
67
/* TODO Take force_share from reopen_queue */
68
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_perm(BlockDriverState *bs, BlockReopenQueue *q,
69
uint64_t cur_perm, cur_shared;
70
bool child_tighten_restr;
71
72
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, q,
73
+ bdrv_child_perm(bs, c->bs, c, c->role, q,
74
cumulative_perms, cumulative_shared_perms,
75
&cur_perm, &cur_shared);
76
ret = bdrv_child_check_perm(c, q, cur_perm, cur_shared, ignore_children,
77
@@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms,
78
/* Update all children */
79
QLIST_FOREACH(c, &bs->children, next) {
80
uint64_t cur_perm, cur_shared;
81
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
82
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
83
cumulative_perms, cumulative_shared_perms,
84
&cur_perm, &cur_shared);
85
bdrv_child_set_perm(c, cur_perm, cur_shared);
86
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
87
uint64_t perms, shared;
88
89
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
90
- bdrv_child_perm(bs, c->bs, c, c->klass, c->role, NULL,
91
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
92
parent_perms, parent_shared, &perms, &shared);
93
94
return bdrv_child_try_set_perm(c, perms, shared, errp);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp)
96
* filtered child.
97
*/
98
static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
99
- const BdrvChildClass *child_class,
100
BdrvChildRole role,
101
BlockReopenQueue *reopen_queue,
102
uint64_t perm, uint64_t shared,
103
@@ -XXX,XX +XXX,XX @@ static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
104
}
105
106
static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
107
- const BdrvChildClass *child_class,
108
BdrvChildRole role,
109
BlockReopenQueue *reopen_queue,
110
uint64_t perm, uint64_t shared,
111
uint64_t *nperm, uint64_t *nshared)
112
{
113
- assert(child_class == &child_of_bds && (role & BDRV_CHILD_COW));
114
+ assert(role & BDRV_CHILD_COW);
115
69
/*
116
/*
70
* Returns an allocated string which is the directory name of this BDS: It
117
* We want consistent read from backing files if the parent needs it.
71
* will be used to make relative filenames absolute by prepending this
118
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
119
}
120
121
static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
122
- const BdrvChildClass *child_class,
123
BdrvChildRole role,
124
BlockReopenQueue *reopen_queue,
125
uint64_t perm, uint64_t shared,
126
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
127
{
128
int flags;
129
130
- assert(child_class == &child_of_bds &&
131
- (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)));
132
+ assert(role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA));
133
134
flags = bdrv_reopen_get_flags(reopen_queue, bs);
135
136
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
137
* Apart from the modifications below, the same permissions are
138
* forwarded and left alone as for filters
139
*/
140
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
141
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
142
perm, shared, &perm, &shared);
143
144
if (role & BDRV_CHILD_METADATA) {
145
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
146
}
147
148
void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
149
- const BdrvChildClass *child_class, BdrvChildRole role,
150
- BlockReopenQueue *reopen_queue,
151
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
152
uint64_t perm, uint64_t shared,
153
uint64_t *nperm, uint64_t *nshared)
154
{
155
- assert(child_class == &child_of_bds);
156
-
157
if (role & BDRV_CHILD_FILTERED) {
158
assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
159
BDRV_CHILD_COW)));
160
- bdrv_filter_default_perms(bs, c, child_class, role, reopen_queue,
161
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
162
perm, shared, nperm, nshared);
163
} else if (role & BDRV_CHILD_COW) {
164
assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
165
- bdrv_default_perms_for_cow(bs, c, child_class, role, reopen_queue,
166
+ bdrv_default_perms_for_cow(bs, c, role, reopen_queue,
167
perm, shared, nperm, nshared);
168
} else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
169
- bdrv_default_perms_for_storage(bs, c, child_class, role, reopen_queue,
170
+ bdrv_default_perms_for_storage(bs, c, role, reopen_queue,
171
perm, shared, nperm, nshared);
172
} else {
173
g_assert_not_reached();
174
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
175
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
176
177
assert(parent_bs->drv);
178
- bdrv_child_perm(parent_bs, child_bs, NULL, child_class, child_role, NULL,
179
+ bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
180
perm, shared_perm, &perm, &shared_perm);
181
182
child = bdrv_root_attach_child(child_bs, child_name, child_class,
183
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
184
if (state->replace_backing_bs && state->new_backing_bs) {
185
uint64_t nperm, nshared;
186
bdrv_child_perm(state->bs, state->new_backing_bs,
187
- NULL, &child_of_bds, bdrv_backing_role(state->bs),
188
+ NULL, bdrv_backing_role(state->bs),
189
bs_queue, state->perm, state->shared_perm,
190
&nperm, &nshared);
191
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
192
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
193
} else {
194
uint64_t nperm, nshared;
195
196
- bdrv_child_perm(parent->state.bs, bs, c, c->klass, c->role, q,
197
+ bdrv_child_perm(parent->state.bs, bs, c, c->role, q,
198
parent->state.perm, parent->state.shared_perm,
199
&nperm, &nshared);
200
201
diff --git a/block/backup-top.c b/block/backup-top.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/block/backup-top.c
204
+++ b/block/backup-top.c
205
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
206
}
207
208
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
209
- const BdrvChildClass *child_class,
210
BdrvChildRole role,
211
BlockReopenQueue *reopen_queue,
212
uint64_t perm, uint64_t shared,
213
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
214
*nperm = BLK_PERM_WRITE;
215
} else {
216
/* Source child */
217
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
218
+ bdrv_default_perms(bs, c, role, reopen_queue,
219
perm, shared, nperm, nshared);
220
221
if (perm & BLK_PERM_WRITE) {
222
diff --git a/block/blkdebug.c b/block/blkdebug.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/block/blkdebug.c
225
+++ b/block/blkdebug.c
226
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
227
}
228
229
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
230
- const BdrvChildClass *child_class,
231
BdrvChildRole role,
232
BlockReopenQueue *reopen_queue,
233
uint64_t perm, uint64_t shared,
234
@@ -XXX,XX +XXX,XX @@ static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
235
{
236
BDRVBlkdebugState *s = bs->opaque;
237
238
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
239
+ bdrv_default_perms(bs, c, role, reopen_queue,
240
perm, shared, nperm, nshared);
241
242
*nperm |= s->take_child_perms;
243
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
244
index XXXXXXX..XXXXXXX 100644
245
--- a/block/blklogwrites.c
246
+++ b/block/blklogwrites.c
247
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
248
}
249
250
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
251
- const BdrvChildClass *child_class,
252
BdrvChildRole role,
253
BlockReopenQueue *ro_q,
254
uint64_t perm, uint64_t shrd,
255
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
256
return;
257
}
258
259
- bdrv_default_perms(bs, c, child_class, role, ro_q, perm, shrd,
260
+ bdrv_default_perms(bs, c, role, ro_q, perm, shrd,
261
nperm, nshrd);
262
}
263
264
diff --git a/block/commit.c b/block/commit.c
265
index XXXXXXX..XXXXXXX 100644
266
--- a/block/commit.c
267
+++ b/block/commit.c
268
@@ -XXX,XX +XXX,XX @@ static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
269
}
270
271
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
272
- const BdrvChildClass *child_class,
273
BdrvChildRole role,
274
BlockReopenQueue *reopen_queue,
275
uint64_t perm, uint64_t shared,
276
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/copy-on-read.c
279
+++ b/block/copy-on-read.c
280
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
281
#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
282
283
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
284
- const BdrvChildClass *child_class,
285
BdrvChildRole role,
286
BlockReopenQueue *reopen_queue,
287
uint64_t perm, uint64_t shared,
288
diff --git a/block/mirror.c b/block/mirror.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/block/mirror.c
291
+++ b/block/mirror.c
292
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
293
}
294
295
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
296
- const BdrvChildClass *child_class,
297
BdrvChildRole role,
298
BlockReopenQueue *reopen_queue,
299
uint64_t perm, uint64_t shared,
72
diff --git a/block/quorum.c b/block/quorum.c
300
diff --git a/block/quorum.c b/block/quorum.c
73
index XXXXXXX..XXXXXXX 100644
301
index XXXXXXX..XXXXXXX 100644
74
--- a/block/quorum.c
302
--- a/block/quorum.c
75
+++ b/block/quorum.c
303
+++ b/block/quorum.c
76
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
304
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
77
bs->full_open_options = opts;
305
}
78
}
306
79
307
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
80
+static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
308
- const BdrvChildClass *child_class,
81
+ bool backing_overridden)
309
BdrvChildRole role,
82
+{
310
BlockReopenQueue *reopen_queue,
83
+ BDRVQuorumState *s = bs->opaque;
311
uint64_t perm, uint64_t shared,
84
+ QList *children_list;
312
diff --git a/block/replication.c b/block/replication.c
85
+ int i;
313
index XXXXXXX..XXXXXXX 100644
86
+
314
--- a/block/replication.c
87
+ /*
315
+++ b/block/replication.c
88
+ * The generic implementation for gathering child options in
316
@@ -XXX,XX +XXX,XX @@ static void replication_close(BlockDriverState *bs)
89
+ * bdrv_refresh_filename() would use the names of the children
317
}
90
+ * as specified for bdrv_open_child() or bdrv_attach_child(),
318
91
+ * which is "children.%u" with %u being a value
319
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
92
+ * (s->next_child_index) that is incremented each time a new child
320
- const BdrvChildClass *child_class,
93
+ * is added (and never decremented). Since children can be
321
BdrvChildRole role,
94
+ * deleted at runtime, there may be gaps in that enumeration.
322
BlockReopenQueue *reopen_queue,
95
+ * When creating a new quorum BDS and specifying the children for
323
uint64_t perm, uint64_t shared,
96
+ * it through runtime options, the enumeration used there may not
324
diff --git a/block/vvfat.c b/block/vvfat.c
97
+ * have any gaps, though.
325
index XXXXXXX..XXXXXXX 100644
98
+ *
326
--- a/block/vvfat.c
99
+ * Therefore, we have to create a new gap-less enumeration here
327
+++ b/block/vvfat.c
100
+ * (which we can achieve by simply putting all of the children's
328
@@ -XXX,XX +XXX,XX @@ err:
101
+ * full_open_options into a QList).
329
}
102
+ *
330
103
+ * XXX: Note that there are issues with the current child option
331
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
104
+ * structure quorum uses (such as the fact that children do
332
- const BdrvChildClass *child_class,
105
+ * not really have unique permanent names). Therefore, this
333
BdrvChildRole role,
106
+ * is going to have to change in the future and ideally we
334
BlockReopenQueue *reopen_queue,
107
+ * want quorum to be covered by the generic implementation.
335
uint64_t perm, uint64_t shared,
108
+ */
336
@@ -XXX,XX +XXX,XX @@ static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
109
+
337
{
110
+ children_list = qlist_new();
338
BDRVVVFATState *s = bs->opaque;
111
+ qdict_put(target, "children", children_list);
339
112
+
340
- assert(c == s->qcow ||
113
+ for (i = 0; i < s->num_children; i++) {
341
- (child_class == &child_of_bds && (role & BDRV_CHILD_COW)));
114
+ qlist_append(children_list,
342
+ assert(c == s->qcow || (role & BDRV_CHILD_COW));
115
+ qobject_ref(s->children[i]->bs->full_open_options));
343
116
+ }
344
if (c == s->qcow) {
117
+}
345
/* This is a private node, nobody should try to attach to it */
118
+
346
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
119
static char *quorum_dirname(BlockDriverState *bs, Error **errp)
347
index XXXXXXX..XXXXXXX 100644
120
{
348
--- a/tests/test-bdrv-drain.c
121
/* In general, there are multiple BDSs with different dirnames below this
349
+++ b/tests/test-bdrv-drain.c
122
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
350
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_preadv(BlockDriverState *bs,
123
.bdrv_open = quorum_open,
124
.bdrv_close = quorum_close,
125
.bdrv_refresh_filename = quorum_refresh_filename,
126
+ .bdrv_gather_child_options = quorum_gather_child_options,
127
.bdrv_dirname = quorum_dirname,
128
129
.bdrv_co_flush_to_disk = quorum_co_flush,
130
diff --git a/block/vmdk.c b/block/vmdk.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/vmdk.c
133
+++ b/block/vmdk.c
134
@@ -XXX,XX +XXX,XX @@
135
#include "qapi/error.h"
136
#include "block/block_int.h"
137
#include "sysemu/block-backend.h"
138
+#include "qapi/qmp/qdict.h"
139
#include "qapi/qmp/qerror.h"
140
#include "qemu/error-report.h"
141
#include "qemu/module.h"
142
@@ -XXX,XX +XXX,XX @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
143
return 0;
351
return 0;
144
}
352
}
145
353
146
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
354
-static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
147
+ bool backing_overridden)
355
- const BdrvChildClass *child_class,
148
+{
356
- BdrvChildRole role,
149
+ /* No children but file and backing can be explicitly specified (TODO) */
357
- BlockReopenQueue *reopen_queue,
150
+ qdict_put(target, "file",
358
- uint64_t perm, uint64_t shared,
151
+ qobject_ref(bs->file->bs->full_open_options));
359
- uint64_t *nperm, uint64_t *nshared)
152
+
360
-{
153
+ if (backing_overridden) {
361
- /*
154
+ if (bs->backing) {
362
- * bdrv_default_perms() accepts nothing else, so disguise
155
+ qdict_put(target, "backing",
363
- * detach_by_driver_cb_parent.
156
+ qobject_ref(bs->backing->bs->full_open_options));
364
- */
157
+ } else {
365
- child_class = &child_of_bds;
158
+ qdict_put_null(target, "backing");
366
-
159
+ }
367
- bdrv_default_perms(bs, c, child_class, role, reopen_queue,
160
+ }
368
- perm, shared, nperm, nshared);
161
+}
369
-}
162
+
370
-
163
static QemuOptsList vmdk_create_opts = {
371
static int bdrv_test_change_backing_file(BlockDriverState *bs,
164
.name = "vmdk-create-opts",
372
const char *backing_file,
165
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
373
const char *backing_fmt)
166
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
374
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_test = {
167
.bdrv_get_specific_info = vmdk_get_specific_info,
375
.bdrv_co_drain_begin = bdrv_test_co_drain_begin,
168
.bdrv_refresh_limits = vmdk_refresh_limits,
376
.bdrv_co_drain_end = bdrv_test_co_drain_end,
169
.bdrv_get_info = vmdk_get_info,
377
170
+ .bdrv_gather_child_options = vmdk_gather_child_options,
378
- .bdrv_child_perm = bdrv_test_child_perm,
171
379
+ .bdrv_child_perm = bdrv_default_perms,
172
.supports_backing = true,
380
173
.create_opts = &vmdk_create_opts,
381
.bdrv_change_backing_file = bdrv_test_change_backing_file,
382
};
383
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
384
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/test-bdrv-graph-mod.c
386
+++ b/tests/test-bdrv-graph-mod.c
387
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_pass_through = {
388
};
389
390
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
391
- const BdrvChildClass *child_class,
392
BdrvChildRole role,
393
BlockReopenQueue *reopen_queue,
394
uint64_t perm, uint64_t shared,
174
--
395
--
175
2.20.1
396
2.25.4
176
397
177
398
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
The QEMU_PACKED is causing a compiler warning/error with GCC 9:
3
Fix when building with -Os:
4
4
5
CC block/nvme.o
5
CC block/block-copy.o
6
block/nvme.c: In function ‘nvme_create_queue_pair’:
6
block/block-copy.c: In function ‘block_copy_task_entry’:
7
block/nvme.c:209:22: error: taking address of packed member of
7
block/block-copy.c:428:38: error: ‘error_is_read’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
8
‘struct <anonymous>’ may result in an unaligned pointer value
8
428 | t->call_state->error_is_read = error_is_read;
9
[-Werror=address-of-packed-member]
9
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
10
209 | q->sq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale];
11
10
12
All members of the struct are naturally aligned, so there should
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
not be the need for QEMU_PACKED here, and the following QEMU_BUILD_BUG_ON
12
Message-Id: <20200507121129.29760-2-philmd@redhat.com>
14
also ensures that there is no padding. Thus simply remove the QEMU_PACKED
13
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
15
---
23
block/nvme.c | 2 +-
16
block/block-copy.c | 2 +-
24
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
25
18
26
diff --git a/block/nvme.c b/block/nvme.c
19
diff --git a/block/block-copy.c b/block/block-copy.c
27
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
28
--- a/block/nvme.c
21
--- a/block/block-copy.c
29
+++ b/block/nvme.c
22
+++ b/block/block-copy.c
30
@@ -XXX,XX +XXX,XX @@ typedef volatile struct {
23
@@ -XXX,XX +XXX,XX @@ out:
31
uint8_t reserved1[0xec0];
24
static coroutine_fn int block_copy_task_entry(AioTask *task)
32
uint8_t cmd_set_specfic[0x100];
25
{
33
uint32_t doorbells[];
26
BlockCopyTask *t = container_of(task, BlockCopyTask, task);
34
-} QEMU_PACKED NVMeRegs;
27
- bool error_is_read;
35
+} NVMeRegs;
28
+ bool error_is_read = false;
36
29
int ret;
37
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
30
38
31
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
39
--
32
--
40
2.20.1
33
2.25.4
41
34
42
35
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Error reporting for user_creatable_add_opts_foreach was changed so that
3
block_copy_do_copy() is static, only used in block_copy_task_entry
4
it no longer called 'error_report_err' in:
4
with the error_is_read argument set. No need to check for it,
5
simplify.
5
6
6
commit 7e1e0c11127bde81cff260fc6859690435c509d6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Author: Markus Armbruster <armbru@redhat.com>
8
Message-Id: <20200507121129.29760-3-philmd@redhat.com>
8
Date: Wed Oct 17 10:26:43 2018 +0200
9
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
11
---
22
qemu-img.c | 26 +++++++++++++-------------
12
block/block-copy.c | 12 +++---------
23
1 file changed, 13 insertions(+), 13 deletions(-)
13
1 file changed, 3 insertions(+), 9 deletions(-)
24
14
25
diff --git a/qemu-img.c b/qemu-img.c
15
diff --git a/block/block-copy.c b/block/block-copy.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
17
--- a/block/block-copy.c
28
+++ b/qemu-img.c
18
+++ b/block/block-copy.c
29
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
30
20
~BDRV_REQ_WRITE_COMPRESSED);
31
if (qemu_opts_foreach(&qemu_object_opts,
21
if (ret < 0) {
32
user_creatable_add_opts_foreach,
22
trace_block_copy_write_zeroes_fail(s, offset, ret);
33
- NULL, NULL)) {
23
- if (error_is_read) {
34
+ NULL, &error_fatal)) {
24
- *error_is_read = false;
35
goto fail;
25
- }
26
+ *error_is_read = false;
27
}
28
return ret;
36
}
29
}
37
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
38
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
31
ret = bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0);
39
32
if (ret < 0) {
40
if (qemu_opts_foreach(&qemu_object_opts,
33
trace_block_copy_read_fail(s, offset, ret);
41
user_creatable_add_opts_foreach,
34
- if (error_is_read) {
42
- NULL, NULL)) {
35
- *error_is_read = true;
43
+ NULL, &error_fatal)) {
36
- }
44
return 1;
37
+ *error_is_read = true;
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
48
49
if (qemu_opts_foreach(&qemu_object_opts,
50
user_creatable_add_opts_foreach,
51
- NULL, NULL)) {
52
+ NULL, &error_fatal)) {
53
return 1;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
57
58
if (qemu_opts_foreach(&qemu_object_opts,
59
user_creatable_add_opts_foreach,
60
- NULL, NULL)) {
61
+ NULL, &error_fatal)) {
62
ret = 2;
63
goto out4;
64
}
65
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
66
67
if (qemu_opts_foreach(&qemu_object_opts,
68
user_creatable_add_opts_foreach,
69
- NULL, NULL)) {
70
+ NULL, &error_fatal)) {
71
goto fail_getopt;
72
}
73
74
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
75
76
if (qemu_opts_foreach(&qemu_object_opts,
77
user_creatable_add_opts_foreach,
78
- NULL, NULL)) {
79
+ NULL, &error_fatal)) {
80
return 1;
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
84
85
if (qemu_opts_foreach(&qemu_object_opts,
86
user_creatable_add_opts_foreach,
87
- NULL, NULL)) {
88
+ NULL, &error_fatal)) {
89
return 1;
90
}
91
92
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
93
94
if (qemu_opts_foreach(&qemu_object_opts,
95
user_creatable_add_opts_foreach,
96
- NULL, NULL)) {
97
+ NULL, &error_fatal)) {
98
return 1;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
102
103
if (qemu_opts_foreach(&qemu_object_opts,
104
user_creatable_add_opts_foreach,
105
- NULL, NULL)) {
106
+ NULL, &error_fatal)) {
107
return 1;
108
}
109
110
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
111
112
if (qemu_opts_foreach(&qemu_object_opts,
113
user_creatable_add_opts_foreach,
114
- NULL, NULL)) {
115
+ NULL, &error_fatal)) {
116
return 1;
117
}
118
119
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
120
121
if (qemu_opts_foreach(&qemu_object_opts,
122
user_creatable_add_opts_foreach,
123
- NULL, NULL)) {
124
+ NULL, &error_fatal)) {
125
ret = -1;
126
goto out_no_progress;
127
}
128
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
129
130
if (qemu_opts_foreach(&qemu_object_opts,
131
user_creatable_add_opts_foreach,
132
- NULL, NULL)) {
133
+ NULL, &error_fatal)) {
134
ret = -1;
135
goto out;
38
goto out;
136
}
39
}
137
@@ -XXX,XX +XXX,XX @@ static int img_measure(int argc, char **argv)
40
138
41
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_copy_do_copy(BlockCopyState *s,
139
if (qemu_opts_foreach(&qemu_object_opts,
42
s->write_flags);
140
user_creatable_add_opts_foreach,
43
if (ret < 0) {
141
- NULL, NULL)) {
44
trace_block_copy_write_fail(s, offset, ret);
142
+ NULL, &error_fatal)) {
45
- if (error_is_read) {
46
- *error_is_read = false;
47
- }
48
+ *error_is_read = false;
143
goto out;
49
goto out;
144
}
50
}
145
51
146
--
52
--
147
2.20.1
53
2.25.4
148
54
149
55
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: John Snow <jsnow@redhat.com>
2
2
3
filter_qmp_testfiles() currently filters the filename only for specific
3
Shift the logging initialization up to occur prior to validation checks,
4
keys. However, there are more keys that take filenames (such as
4
so that notrun() messages still get printed to console.
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
5
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
(Also, remove the "debugging messages active" message, because we don't
10
Reviewed-by: John Snow <jsnow@redhat.com>
7
need to see that hundreds of times per iotest suite run.)
11
Message-id: 20190210145736.1486-8-mreitz@redhat.com
8
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20200514201614.19941-2-jsnow@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
tests/qemu-iotests/iotests.py | 2 +-
13
tests/qemu-iotests/iotests.py | 11 +++++------
15
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 5 insertions(+), 6 deletions(-)
16
15
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
18
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def filter_testfiles(msg):
20
@@ -XXX,XX +XXX,XX @@ def execute_setup_common(supported_fmts: Sequence[str] = (),
22
21
sys.stderr.write('Please run this test via the "check" script\n')
23
def filter_qmp_testfiles(qmsg):
22
sys.exit(os.EX_USAGE)
24
def _filter(key, value):
23
25
- if key == 'filename' or key == 'backing-file':
24
+ debug = '-d' in sys.argv
26
+ if is_str(value):
25
+ if debug:
27
return filter_testfiles(value)
26
+ sys.argv.remove('-d')
28
return value
27
+ logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
29
return filter_qmp(qmsg, _filter)
28
+
29
_verify_image_format(supported_fmts, unsupported_fmts)
30
_verify_protocol(supported_protocols, unsupported_protocols)
31
_verify_platform(supported=supported_platforms)
32
_verify_cache_mode(supported_cache_modes)
33
_verify_aio_mode(supported_aio_modes)
34
35
- debug = '-d' in sys.argv
36
- if debug:
37
- sys.argv.remove('-d')
38
- logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
39
- logger.debug("iotests debugging messages active")
40
-
41
return debug
42
43
def execute_test(*args, test_function=None, **kwargs):
30
--
44
--
31
2.20.1
45
2.25.4
32
46
33
47
diff view generated by jsdifflib
1
Similar to how qemu_co_sleep_ns() allows preemption from an external
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
coroutine entry, allow reentering qio_channel_yield() early.
3
2
3
One might find interesting to look at AHCI IRQs.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-Id: <20200504094858.5975-1-f4bug@amsat.org>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Acked-by: John Snow <jsnow@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
hw/ide/ahci.c | 1 +
7
io/channel.c | 10 ++++++++++
12
1 file changed, 1 insertion(+)
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/hw/ide/ahci.c b/hw/ide/ahci.c
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/include/io/channel.h
16
--- a/hw/ide/ahci.c
13
+++ b/include/io/channel.h
17
+++ b/hw/ide/ahci.c
14
@@ -XXX,XX +XXX,XX @@ void qio_channel_detach_aio_context(QIOChannel *ioc);
18
@@ -XXX,XX +XXX,XX @@ static void ahci_cmd_done(IDEDMA *dma)
15
* addition, no two coroutine can be waiting on the same condition
19
16
* and channel at the same time.
20
static void ahci_irq_set(void *opaque, int n, int level)
17
*
21
{
18
- * This must only be called from coroutine context
22
+ qemu_log_mask(LOG_UNIMP, "ahci: IRQ#%d level:%d\n", n, level);
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
*/
24
-void qio_channel_yield(QIOChannel *ioc,
25
- GIOCondition condition);
26
+void coroutine_fn qio_channel_yield(QIOChannel *ioc,
27
+ GIOCondition condition);
28
29
/**
30
* qio_channel_wait:
31
diff --git a/io/channel.c b/io/channel.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/io/channel.c
34
+++ b/io/channel.c
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qio_channel_yield(QIOChannel *ioc,
36
}
37
qio_channel_set_aio_fd_handlers(ioc);
38
qemu_coroutine_yield();
39
+
40
+ /* Allow interrupting the operation by reentering the coroutine other than
41
+ * through the aio_fd_handlers. */
42
+ if (condition == G_IO_IN && ioc->read_coroutine) {
43
+ ioc->read_coroutine = NULL;
44
+ qio_channel_set_aio_fd_handlers(ioc);
45
+ } else if (condition == G_IO_OUT && ioc->write_coroutine) {
46
+ ioc->write_coroutine = NULL;
47
+ qio_channel_set_aio_fd_handlers(ioc);
48
+ }
49
}
23
}
50
24
51
25
static const IDEDMAOps ahci_dma_ops = {
52
--
26
--
53
2.20.1
27
2.25.4
54
28
55
29
diff view generated by jsdifflib
Deleted patch
1
qio_channel_yield() now updates ioc->read_write/coroutine and calls
2
qio_channel_set_aio_fd_handlers(), so the code in the handlers has
3
become redundant and can be removed.
4
1
5
This does not make a difference in intermediate states because
6
aio_co_wake() really enters the coroutine immediately here: These
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
11
To make these conditions more obvious, assert the right AioContext.
12
13
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
io/channel.c | 12 ++++++------
17
1 file changed, 6 insertions(+), 6 deletions(-)
18
19
diff --git a/io/channel.c b/io/channel.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/io/channel.c
22
+++ b/io/channel.c
23
@@ -XXX,XX +XXX,XX @@ off_t qio_channel_io_seek(QIOChannel *ioc,
24
}
25
26
27
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
28
-
29
static void qio_channel_restart_read(void *opaque)
30
{
31
QIOChannel *ioc = opaque;
32
Coroutine *co = ioc->read_coroutine;
33
34
- ioc->read_coroutine = NULL;
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
}
41
42
@@ -XXX,XX +XXX,XX @@ static void qio_channel_restart_write(void *opaque)
43
QIOChannel *ioc = opaque;
44
Coroutine *co = ioc->write_coroutine;
45
46
- ioc->write_coroutine = NULL;
47
- qio_channel_set_aio_fd_handlers(ioc);
48
+ /* Assert that aio_co_wake() reenters the coroutine directly */
49
+ assert(qemu_get_current_aio_context() ==
50
+ qemu_coroutine_get_aio_context(co));
51
aio_co_wake(co);
52
}
53
54
--
55
2.20.1
56
57
diff view generated by jsdifflib
Deleted patch
1
Instead of using the convenience wrapper qio_channel_read_all_eof(), use
2
the lower level QIOChannel API. This means duplicating some code, but
3
we'll need this because this coroutine yield is special: We want it to
4
be interruptible so that nbd_client_attach_aio_context() can correctly
5
reenter the coroutine.
6
1
7
This moves the bdrv_dec/inc_in_flight() pair into nbd_read_eof(), so
8
that connection_co will always sit in this exact qio_channel_yield()
9
call when bdrv_drain() returns.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
---
14
include/block/nbd.h | 4 ++--
15
block/nbd-client.c | 8 +-------
16
nbd/client.c | 46 ++++++++++++++++++++++++++++++++++++---------
17
3 files changed, 40 insertions(+), 18 deletions(-)
18
19
diff --git a/include/block/nbd.h b/include/block/nbd.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/nbd.h
22
+++ b/include/block/nbd.h
23
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
24
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
25
Error **errp);
26
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
27
-int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
28
- Error **errp);
29
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
30
+ NBDReply *reply, Error **errp);
31
int nbd_client(int fd);
32
int nbd_disconnect(int fd);
33
int nbd_errno_to_system_errno(int err);
34
diff --git a/block/nbd-client.c b/block/nbd-client.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/nbd-client.c
37
+++ b/block/nbd-client.c
38
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
39
*
40
* Therefore we keep an additional in_flight reference all the time and
41
* only drop it temporarily here.
42
- *
43
- * FIXME This is not safe because the QIOChannel could wake up the
44
- * coroutine for a second time; it is not prepared for coroutine
45
- * resumption from external code.
46
*/
47
- bdrv_dec_in_flight(s->bs);
48
assert(s->reply.handle == 0);
49
- ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
50
- bdrv_inc_in_flight(s->bs);
51
+ ret = nbd_receive_reply(s->bs, s->ioc, &s->reply, &local_err);
52
53
if (local_err) {
54
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
55
diff --git a/nbd/client.c b/nbd/client.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/nbd/client.c
58
+++ b/nbd/client.c
59
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
60
* negative errno on failure (errp is set)
61
*/
62
static inline int coroutine_fn
63
-nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
64
+nbd_read_eof(BlockDriverState *bs, QIOChannel *ioc, void *buffer, size_t size,
65
+ Error **errp)
66
{
67
- int ret;
68
+ bool partial = false;
69
70
assert(size);
71
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
72
- if (ret < 0) {
73
- ret = -EIO;
74
+ while (size > 0) {
75
+ struct iovec iov = { .iov_base = buffer, .iov_len = size };
76
+ ssize_t len;
77
+
78
+ len = qio_channel_readv(ioc, &iov, 1, errp);
79
+ if (len == QIO_CHANNEL_ERR_BLOCK) {
80
+ bdrv_dec_in_flight(bs);
81
+ qio_channel_yield(ioc, G_IO_IN);
82
+ bdrv_inc_in_flight(bs);
83
+ continue;
84
+ } else if (len < 0) {
85
+ return -EIO;
86
+ } else if (len == 0) {
87
+ if (partial) {
88
+ error_setg(errp,
89
+ "Unexpected end-of-file before all bytes were read");
90
+ return -EIO;
91
+ } else {
92
+ return 0;
93
+ }
94
+ }
95
+
96
+ partial = true;
97
+ size -= len;
98
+ buffer = (uint8_t*) buffer + len;
99
}
100
- return ret;
101
+ return 1;
102
}
103
104
/* nbd_receive_reply
105
+ *
106
+ * Decreases bs->in_flight while waiting for a new reply. This yield is where
107
+ * we wait indefinitely and the coroutine must be able to be safely reentered
108
+ * for nbd_client_attach_aio_context().
109
+ *
110
* Returns 1 on success
111
* 0 on eof, when no data was read (errp is not set)
112
* negative errno on failure (errp is set)
113
*/
114
-int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
115
- Error **errp)
116
+int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
117
+ NBDReply *reply, Error **errp)
118
{
119
int ret;
120
const char *type;
121
122
- ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
123
+ ret = nbd_read_eof(bs, ioc, &reply->magic, sizeof(reply->magic), errp);
124
if (ret <= 0) {
125
return ret;
126
}
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
Deleted patch
1
bdrv_drain() must not leave connection_co scheduled, so bs->in_flight
2
needs to be increased while the coroutine is waiting to be scheduled
3
in the new AioContext after nbd_client_attach_aio_context().
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
block/nbd-client.c | 20 ++++++++++++++++++--
8
1 file changed, 18 insertions(+), 2 deletions(-)
9
10
diff --git a/block/nbd-client.c b/block/nbd-client.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/nbd-client.c
13
+++ b/block/nbd-client.c
14
@@ -XXX,XX +XXX,XX @@ void nbd_client_detach_aio_context(BlockDriverState *bs)
15
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
16
}
17
18
+static void nbd_client_attach_aio_context_bh(void *opaque)
19
+{
20
+ BlockDriverState *bs = opaque;
21
+ NBDClientSession *client = nbd_get_client_session(bs);
22
+
23
+ /* The node is still drained, so we know the coroutine has yielded in
24
+ * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
25
+ * entered for the first time. Both places are safe for entering the
26
+ * coroutine.*/
27
+ qemu_aio_coroutine_enter(bs->aio_context, client->connection_co);
28
+ bdrv_dec_in_flight(bs);
29
+}
30
+
31
void nbd_client_attach_aio_context(BlockDriverState *bs,
32
AioContext *new_context)
33
{
34
NBDClientSession *client = nbd_get_client_session(bs);
35
qio_channel_attach_aio_context(QIO_CHANNEL(client->ioc), new_context);
36
37
- /* FIXME Really need a bdrv_inc_in_flight() here */
38
- aio_co_schedule(new_context, client->connection_co);
39
+ bdrv_inc_in_flight(bs);
40
+
41
+ /* Need to wait here for the BH to run because the BH must run while the
42
+ * node is still drained. */
43
+ aio_wait_bh_oneshot(new_context, nbd_client_attach_aio_context_bh, bs);
44
}
45
46
void nbd_client_close(BlockDriverState *bs)
47
--
48
2.20.1
49
50
diff view generated by jsdifflib
Deleted patch
1
The explicit aio_poll() call in bdrv_set_aio_context() was added in
2
commit c2b6428d388 as a workaround for bdrv_drain() failing to achieve
3
to actually quiesce everything (specifically the NBD client code to
4
switch AioContext).
5
1
6
Now that the NBD client has been fixed to complete this operation during
7
bdrv_drain(), we don't need the workaround any more.
8
9
It was wrong anyway: aio_poll() must always be run in the home thread of
10
the AioContext.
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
---
15
block.c | 4 ----
16
1 file changed, 4 deletions(-)
17
18
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
23
bdrv_parent_drained_begin(bs, NULL, false);
24
bdrv_drain(bs); /* ensure there are no in-flight requests */
25
26
- while (aio_poll(ctx, false)) {
27
- /* wait for all bottom halves to execute */
28
- }
29
-
30
bdrv_detach_aio_context(bs);
31
32
/* This function executes in the old AioContext so acquire the new one in
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
1
aio_poll() has an existing assertion that the function is only called
1
test_overlapping_3() throttles its active commit job so it can be sure
2
from the AioContext's home thread if blocking is allowed.
2
the job is still busy when it checks that you can't start a conflicting
3
streaming job.
3
4
4
This is not enough, some handlers make assumptions about the thread they
5
However, it only sets the commit job back to full speed when it is
5
run in. Extend the assertion to non-blocking calls, too.
6
ready, which takes a few seconds while it's throttled. We can already
7
reset the limit after having checked that block-stream returns an error
8
and save these seconds.
6
9
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>
11
Message-Id: <20200513100025.33543-1-kwolf@redhat.com>
12
Reviewed-by: Alberto Garcia <berto@igalia.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
14
---
10
util/aio-posix.c | 3 ++-
15
tests/qemu-iotests/030 | 6 +++---
11
1 file changed, 2 insertions(+), 1 deletion(-)
16
1 file changed, 3 insertions(+), 3 deletions(-)
12
17
13
diff --git a/util/aio-posix.c b/util/aio-posix.c
18
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100755
15
--- a/util/aio-posix.c
20
--- a/tests/qemu-iotests/030
16
+++ b/util/aio-posix.c
21
+++ b/tests/qemu-iotests/030
17
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
22
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
18
int64_t timeout;
23
self.assert_qmp(result, 'error/desc',
19
int64_t start = 0;
24
"Node 'node5' is busy: block device is in use by block job: commit")
20
25
21
+ assert(in_aio_context_home_thread(ctx));
26
+ result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
27
+ self.assert_qmp(result, 'return', {})
22
+
28
+
23
/* aio_notify can avoid the expensive event_notifier_set if
29
event = self.vm.event_wait(name='BLOCK_JOB_READY')
24
* everything (file descriptors, bottom halves, timers) will
30
self.assert_qmp(event, 'data/device', 'commit-drive0')
25
* be re-evaluated before the next blocking poll(). This is
31
self.assert_qmp(event, 'data/type', 'commit')
26
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
32
self.assert_qmp_absent(event, 'data/error')
27
* so disable the optimization now.
33
28
*/
34
- result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
29
if (blocking) {
35
- self.assert_qmp(result, 'return', {})
30
- assert(in_aio_context_home_thread(ctx));
36
-
31
atomic_add(&ctx->notify_me, 2);
37
result = self.vm.qmp('block-job-complete', device='commit-drive0')
32
}
38
self.assert_qmp(result, 'return', {})
33
39
34
--
40
--
35
2.20.1
41
2.25.4
36
42
37
43
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add two tests of node graph modification.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
tests/test-bdrv-graph-mod.c | 198 ++++++++++++++++++++++++++++++++++++
9
tests/Makefile.include | 2 +
10
2 files changed, 200 insertions(+)
11
create mode 100644 tests/test-bdrv-graph-mod.c
12
13
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/tests/test-bdrv-graph-mod.c
18
@@ -XXX,XX +XXX,XX @@
19
+/*
20
+ * Block node graph modifications tests
21
+ *
22
+ * Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
23
+ *
24
+ * This program is free software; you can redistribute it and/or modify
25
+ * it under the terms of the GNU General Public License as published by
26
+ * the Free Software Foundation; either version 2 of the License, or
27
+ * (at your option) any later version.
28
+ *
29
+ * This program is distributed in the hope that it will be useful,
30
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+ * GNU General Public License for more details.
33
+ *
34
+ * You should have received a copy of the GNU General Public License
35
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+ *
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "qapi/error.h"
41
+#include "block/block_int.h"
42
+#include "sysemu/block-backend.h"
43
+
44
+static BlockDriver bdrv_pass_through = {
45
+ .format_name = "pass-through",
46
+ .bdrv_child_perm = bdrv_filter_default_perms,
47
+};
48
+
49
+static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
50
+ const BdrvChildRole *role,
51
+ BlockReopenQueue *reopen_queue,
52
+ uint64_t perm, uint64_t shared,
53
+ uint64_t *nperm, uint64_t *nshared)
54
+{
55
+ *nperm = 0;
56
+ *nshared = BLK_PERM_ALL;
57
+}
58
+
59
+static BlockDriver bdrv_no_perm = {
60
+ .format_name = "no-perm",
61
+ .bdrv_child_perm = no_perm_default_perms,
62
+};
63
+
64
+static BlockDriverState *no_perm_node(const char *name)
65
+{
66
+ return bdrv_new_open_driver(&bdrv_no_perm, name, BDRV_O_RDWR, &error_abort);
67
+}
68
+
69
+static BlockDriverState *pass_through_node(const char *name)
70
+{
71
+ return bdrv_new_open_driver(&bdrv_pass_through, name,
72
+ BDRV_O_RDWR, &error_abort);
73
+}
74
+
75
+/*
76
+ * test_update_perm_tree
77
+ *
78
+ * When checking node for a possibility to update permissions, it's subtree
79
+ * should be correctly checked too. New permissions for each node should be
80
+ * calculated and checked in context of permissions of other nodes. If we
81
+ * check new permissions of the node only in context of old permissions of
82
+ * its neighbors, we can finish up with wrong permission graph.
83
+ *
84
+ * This test firstly create the following graph:
85
+ * +--------+
86
+ * | root |
87
+ * +--------+
88
+ * |
89
+ * | perm: write, read
90
+ * | shared: except write
91
+ * v
92
+ * +-------------------+ +----------------+
93
+ * | passtrough filter |---------->| null-co node |
94
+ * +-------------------+ +----------------+
95
+ *
96
+ *
97
+ * and then, tries to append filter under node. Expected behavior: fail.
98
+ * Otherwise we'll get the following picture, with two BdrvChild'ren, having
99
+ * write permission to one node, without actually sharing it.
100
+ *
101
+ * +--------+
102
+ * | root |
103
+ * +--------+
104
+ * |
105
+ * | perm: write, read
106
+ * | shared: except write
107
+ * v
108
+ * +-------------------+
109
+ * | passtrough filter |
110
+ * +-------------------+
111
+ * | |
112
+ * perm: write, read | | perm: write, read
113
+ * shared: except write | | shared: except write
114
+ * v v
115
+ * +----------------+
116
+ * | null co node |
117
+ * +----------------+
118
+ */
119
+static void test_update_perm_tree(void)
120
+{
121
+ Error *local_err = NULL;
122
+
123
+ BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
124
+ BLK_PERM_ALL & ~BLK_PERM_WRITE);
125
+ BlockDriverState *bs = no_perm_node("node");
126
+ BlockDriverState *filter = pass_through_node("filter");
127
+
128
+ blk_insert_bs(root, bs, &error_abort);
129
+
130
+ bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
131
+
132
+ bdrv_append(filter, bs, &local_err);
133
+
134
+ g_assert_nonnull(local_err);
135
+
136
+ bdrv_unref(bs);
137
+ blk_unref(root);
138
+}
139
+
140
+/*
141
+ * test_should_update_child
142
+ *
143
+ * Test that bdrv_replace_node, and concretely should_update_child
144
+ * do the right thing, i.e. not creating loops on the graph.
145
+ *
146
+ * The test does the following:
147
+ * 1. initial graph:
148
+ *
149
+ * +------+ +--------+
150
+ * | root | | filter |
151
+ * +------+ +--------+
152
+ * | |
153
+ * root| target|
154
+ * v v
155
+ * +------+ +--------+
156
+ * | node |<---------| target |
157
+ * +------+ backing +--------+
158
+ *
159
+ * 2. Append @filter above @node. If should_update_child works correctly,
160
+ * it understands, that backing child of @target should not be updated,
161
+ * as it will create a loop on node graph. Resulting picture should
162
+ * be the left one, not the right:
163
+ *
164
+ * +------+ +------+
165
+ * | root | | root |
166
+ * +------+ +------+
167
+ * | |
168
+ * root| root|
169
+ * v v
170
+ * +--------+ target +--------+ target
171
+ * | filter |--------------+ | filter |--------------+
172
+ * +--------+ | +--------+ |
173
+ * | | | ^ v
174
+ * backing| | backing| | +--------+
175
+ * v v | +-----------| target |
176
+ * +------+ +--------+ v backing +--------+
177
+ * | node |<---------| target | +------+
178
+ * +------+ backing +--------+ | node |
179
+ * +------+
180
+ *
181
+ * (good picture) (bad picture)
182
+ *
183
+ */
184
+static void test_should_update_child(void)
185
+{
186
+ BlockBackend *root = blk_new(0, BLK_PERM_ALL);
187
+ BlockDriverState *bs = no_perm_node("node");
188
+ BlockDriverState *filter = no_perm_node("filter");
189
+ BlockDriverState *target = no_perm_node("target");
190
+
191
+ blk_insert_bs(root, bs, &error_abort);
192
+
193
+ bdrv_set_backing_hd(target, bs, &error_abort);
194
+
195
+ g_assert(target->backing->bs == bs);
196
+ bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
197
+ bdrv_append(filter, bs, &error_abort);
198
+ g_assert(target->backing->bs == bs);
199
+
200
+ bdrv_unref(bs);
201
+ blk_unref(root);
202
+}
203
+
204
+int main(int argc, char *argv[])
205
+{
206
+ bdrv_init();
207
+ qemu_init_main_loop(&error_abort);
208
+
209
+ g_test_init(&argc, &argv, NULL);
210
+
211
+ g_test_add_func("/bdrv-graph-mod/update-perm-tree", test_update_perm_tree);
212
+ g_test_add_func("/bdrv-graph-mod/should-update-child",
213
+ test_should_update_child);
214
+
215
+ return g_test_run();
216
+}
217
diff --git a/tests/Makefile.include b/tests/Makefile.include
218
index XXXXXXX..XXXXXXX 100644
219
--- a/tests/Makefile.include
220
+++ b/tests/Makefile.include
221
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-throttle$(EXESUF)
222
check-unit-y += tests/test-thread-pool$(EXESUF)
223
check-unit-y += tests/test-hbitmap$(EXESUF)
224
check-unit-y += tests/test-bdrv-drain$(EXESUF)
225
+check-unit-y += tests/test-bdrv-graph-mod$(EXESUF)
226
check-unit-y += tests/test-blockjob$(EXESUF)
227
check-unit-y += tests/test-blockjob-txn$(EXESUF)
228
check-unit-y += tests/test-block-backend$(EXESUF)
229
@@ -XXX,XX +XXX,XX @@ tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
230
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
231
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
232
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
233
+tests/test-bdrv-graph-mod$(EXESUF): tests/test-bdrv-graph-mod.o $(test-block-obj-y) $(test-util-obj-y)
234
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
235
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
236
tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y)
237
--
238
2.20.1
239
240
diff view generated by jsdifflib
Deleted patch
1
From: 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
A previous commit removed the default filters for qmp_log with the
4
intention to make them explicit; but this happened only for test 206.
5
There are more tests (for more exotic image formats than qcow2) which
6
require the filename filter, though.
7
8
Note that 237 is still broken for Python 2.x, which is fixed in the next
9
commit.
10
11
Fixes: f8ca8609d8549def45b28e82ecac64adaeee9f12
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Message-id: 20190210145736.1486-2-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/210 | 5 +++--
18
tests/qemu-iotests/211 | 5 +++--
19
tests/qemu-iotests/212 | 5 +++--
20
tests/qemu-iotests/213 | 5 +++--
21
tests/qemu-iotests/237 | 5 +++--
22
5 files changed, 15 insertions(+), 10 deletions(-)
23
24
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
25
index XXXXXXX..XXXXXXX 100755
26
--- a/tests/qemu-iotests/210
27
+++ b/tests/qemu-iotests/210
28
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['luks'])
29
iotests.verify_protocol(supported=['file'])
30
31
def blockdev_create(vm, options):
32
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
33
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
34
+ filters=[iotests.filter_qmp_testfiles])
35
36
if 'return' in result:
37
assert result['return'] == {}
38
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.luks') as disk_path, \
39
'size': 0 })
40
41
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
42
- node_name='imgfile')
43
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
44
45
blockdev_create(vm, { 'driver': imgfmt,
46
'file': 'imgfile',
47
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
48
index XXXXXXX..XXXXXXX 100755
49
--- a/tests/qemu-iotests/211
50
+++ b/tests/qemu-iotests/211
51
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['vdi'])
52
iotests.verify_protocol(supported=['file'])
53
54
def blockdev_create(vm, options):
55
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
56
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
57
+ filters=[iotests.filter_qmp_testfiles])
58
59
if 'return' in result:
60
assert result['return'] == {}
61
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vdi') as disk_path, \
62
'size': 0 })
63
64
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
65
- node_name='imgfile')
66
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
67
68
blockdev_create(vm, { 'driver': imgfmt,
69
'file': 'imgfile',
70
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
71
index XXXXXXX..XXXXXXX 100755
72
--- a/tests/qemu-iotests/212
73
+++ b/tests/qemu-iotests/212
74
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['parallels'])
75
iotests.verify_protocol(supported=['file'])
76
77
def blockdev_create(vm, options):
78
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
79
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
80
+ filters=[iotests.filter_qmp_testfiles])
81
82
if 'return' in result:
83
assert result['return'] == {}
84
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.parallels') as disk_path, \
85
'size': 0 })
86
87
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
88
- node_name='imgfile')
89
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
90
91
blockdev_create(vm, { 'driver': imgfmt,
92
'file': 'imgfile',
93
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
94
index XXXXXXX..XXXXXXX 100755
95
--- a/tests/qemu-iotests/213
96
+++ b/tests/qemu-iotests/213
97
@@ -XXX,XX +XXX,XX @@ iotests.verify_image_format(supported_fmts=['vhdx'])
98
iotests.verify_protocol(supported=['file'])
99
100
def blockdev_create(vm, options):
101
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
102
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
103
+ filters=[iotests.filter_qmp_testfiles])
104
105
if 'return' in result:
106
assert result['return'] == {}
107
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vhdx') as disk_path, \
108
'size': 0 })
109
110
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
111
- node_name='imgfile')
112
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
113
114
blockdev_create(vm, { 'driver': imgfmt,
115
'file': 'imgfile',
116
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
117
index XXXXXXX..XXXXXXX 100755
118
--- a/tests/qemu-iotests/237
119
+++ b/tests/qemu-iotests/237
120
@@ -XXX,XX +XXX,XX @@ from iotests import imgfmt
121
iotests.verify_image_format(supported_fmts=['vmdk'])
122
123
def blockdev_create(vm, options):
124
- result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
125
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
126
+ filters=[iotests.filter_qmp_testfiles])
127
128
if 'return' in result:
129
assert result['return'] == {}
130
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
131
'size': 0 })
132
133
vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
134
- node_name='imgfile')
135
+ node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
136
137
blockdev_create(vm, { 'driver': imgfmt,
138
'file': 'imgfile',
139
--
140
2.20.1
141
142
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
math.ceil() returns an integer on Python 3.x, but a float on Python 2.x.
4
range() always needs integers, so we need an explicit conversion on 2.x
5
(which does not hurt on 3.x).
6
7
It is not quite clear whether we want to support Python 2.x for any
8
prolonged time, but this may as well be fixed along with the other
9
issues some iotests have right now.
10
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Message-id: 20190210145736.1486-3-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/237 | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/237
23
+++ b/tests/qemu-iotests/237
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
25
iotests.log("= %s %d =" % (subfmt, size))
26
iotests.log("")
27
28
- num_extents = math.ceil(size / 2.0**31)
29
+ num_extents = int(math.ceil(size / 2.0**31))
30
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
31
32
vm.launch()
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
With IMGOPTSSYNTAX, $TEST_IMG is useless for this test (it only tests
4
the file-posix protocol driver). Therefore, if $TEST_IMG_FILE is set,
5
use that instead.
6
7
Because this test requires the file protocol, $TEST_IMG_FILE will always
8
be set if $IMGOPTSSYNTAX is true.
9
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: John Snow <jsnow@redhat.com>
12
Message-id: 20190210145736.1486-5-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
tests/qemu-iotests/232 | 4 ++++
16
1 file changed, 4 insertions(+)
17
18
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/232
21
+++ b/tests/qemu-iotests/232
22
@@ -XXX,XX +XXX,XX @@ size=128M
23
24
_make_test_img $size
25
26
+if [ -n "$TEST_IMG_FILE" ]; then
27
+ TEST_IMG=$TEST_IMG_FILE
28
+fi
29
+
30
echo
31
echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
32
echo
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Fixes: 08fcd6111e1949f456e1b232ebeeb0cc17019a92
4
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Message-id: 20190210145736.1486-6-mreitz@redhat.com
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
9
tests/qemu-iotests/207 | 10 +++++++---
10
tests/qemu-iotests/207.out | 4 ++--
11
2 files changed, 9 insertions(+), 5 deletions(-)
12
13
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/207
16
+++ b/tests/qemu-iotests/207
17
@@ -XXX,XX +XXX,XX @@ import re
18
iotests.verify_image_format(supported_fmts=['raw'])
19
iotests.verify_protocol(supported=['ssh'])
20
21
-def filter_hash(msg):
22
- return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg)
23
+def filter_hash(qmsg):
24
+ def _filter(key, value):
25
+ if key == 'hash' and re.match('[0-9a-f]+', value):
26
+ return 'HASH'
27
+ return value
28
+ return iotests.filter_qmp(qmsg, _filter)
29
30
def blockdev_create(vm, options):
31
result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
32
- filters=[iotests.filter_testfiles, filter_hash])
33
+ filters=[iotests.filter_qmp_testfiles, filter_hash])
34
35
if 'return' in result:
36
assert result['return'] == {}
37
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tests/qemu-iotests/207.out
40
+++ b/tests/qemu-iotests/207.out
41
@@ -XXX,XX +XXX,XX @@ Job failed: remote host key does not match host_key_check 'wrong'
42
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
43
{"return": {}}
44
45
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
46
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
47
{"return": {}}
48
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
49
{"return": {}}
50
@@ -XXX,XX +XXX,XX @@ Job failed: remote host key does not match host_key_check 'wrong'
51
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
52
{"return": {}}
53
54
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
55
+{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
56
{"return": {}}
57
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
58
{"return": {}}
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
On Python 2.x, strings are not always unicode strings. This function
4
checks whether a given value is a plain string, or a unicode string (if
5
there is a difference).
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Message-id: 20190210145736.1486-7-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 6 ++++++
13
1 file changed, 6 insertions(+)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def image_size(img):
20
r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img)
21
return json.loads(r)['virtual-size']
22
23
+def is_str(val):
24
+ if sys.version_info.major >= 3:
25
+ return isinstance(val, str)
26
+ else:
27
+ return isinstance(val, str) or isinstance(val, unicode)
28
+
29
test_dir_re = re.compile(r"%s" % test_dir)
30
def filter_test_dir(msg):
31
return test_dir_re.sub("TEST_DIR", msg)
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
8908b253c4ad5f8874c8d13abec169c696a5cd32 has implemented filtering of
4
remote paths for NFS, but forgot SSH. This patch takes care of that.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-9-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/common.rc | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/common.rc
17
+++ b/tests/qemu-iotests/common.rc
18
@@ -XXX,XX +XXX,XX @@ else
19
TEST_IMG="nbd:127.0.0.1:10810"
20
elif [ "$IMGPROTO" = "ssh" ]; then
21
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
22
+ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR"
23
TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE"
24
elif [ "$IMGPROTO" = "nfs" ]; then
25
TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Adding a telnet monitor for no real purpose on a fixed port is not so
4
great. Just use a null monitor instead.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-10-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
scripts/qemu.py | 5 ++---
12
tests/qemu-iotests/045 | 2 +-
13
2 files changed, 3 insertions(+), 4 deletions(-)
14
15
diff --git a/scripts/qemu.py b/scripts/qemu.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/scripts/qemu.py
18
+++ b/scripts/qemu.py
19
@@ -XXX,XX +XXX,XX @@ class QEMUMachine(object):
20
return False
21
22
# This can be used to add an unused monitor instance.
23
- def add_monitor_telnet(self, ip, port):
24
- args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
25
+ def add_monitor_null(self):
26
self._args.append('-monitor')
27
- self._args.append(args)
28
+ self._args.append('null')
29
30
def add_fd(self, fd, fdset, opaque, opts=''):
31
"""
32
diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
33
index XXXXXXX..XXXXXXX 100755
34
--- a/tests/qemu-iotests/045
35
+++ b/tests/qemu-iotests/045
36
@@ -XXX,XX +XXX,XX @@ class TestSCMFd(iotests.QMPTestCase):
37
qemu_img('create', '-f', iotests.imgfmt, image0, '128K')
38
# Add an unused monitor, to verify it works fine when two monitor
39
# instances present
40
- self.vm.add_monitor_telnet("0",4445)
41
+ self.vm.add_monitor_null()
42
self.vm.launch()
43
44
def tearDown(self):
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
LUKS encryption reserves clusters for its own payload data. The size of
4
this area must be included in the qemu-img measure calculation so that
5
we arrive at the correct minimum required image size.
6
7
(Ab)use the qcrypto_block_create() API to determine the payload
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
---
16
block/qcow2.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
17
1 file changed, 71 insertions(+), 1 deletion(-)
18
19
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
22
+++ b/block/qcow2.c
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
24
return ret;
25
}
26
27
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
28
+ size_t headerlen, void *opaque, Error **errp)
29
+{
30
+ size_t *headerlenp = opaque;
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
{
84
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
85
uint64_t virtual_size; /* disk size as seen by guest */
86
uint64_t refcount_bits;
87
uint64_t l2_tables;
88
+ uint64_t luks_payload_size = 0;
89
size_t cluster_size;
90
int version;
91
char *optstr;
92
PreallocMode prealloc;
93
bool has_backing_file;
94
+ bool has_luks;
95
96
/* Parse image creation options */
97
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
98
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
99
has_backing_file = !!optstr;
100
g_free(optstr);
101
102
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
103
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
104
+ g_free(optstr);
105
+
106
+ if (has_luks) {
107
+ size_t headerlen;
108
+
109
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
110
+ goto err;
111
+ }
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
--
129
2.20.1
130
131
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
The previous patch includes the LUKS payload overhead into the qemu-img
4
measure calculation for qcow2. Update qemu-iotests 178 to exercise this
5
new code path.
6
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20190218104525.23674-3-stefanha@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/178 | 8 ++++++++
14
tests/qemu-iotests/178.out.qcow2 | 24 ++++++++++++++++++++++++
15
2 files changed, 32 insertions(+)
16
17
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/178
20
+++ b/tests/qemu-iotests/178
21
@@ -XXX,XX +XXX,XX @@ for ofmt in human json; do
22
# The backing file doesn't need to exist :)
23
$QEMU_IMG measure --output=$ofmt -o backing_file=x \
24
-f "$fmt" -O "$IMGFMT" "$TEST_IMG"
25
+
26
+ echo
27
+ echo "== $fmt input image and LUKS encryption =="
28
+ echo
29
+ $QEMU_IMG measure --output=$ofmt \
30
+ --object secret,id=sec0,data=base \
31
+ -o encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10 \
32
+ -f "$fmt" -O "$IMGFMT" "$TEST_IMG"
33
fi
34
35
echo
36
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/178.out.qcow2
39
+++ b/tests/qemu-iotests/178.out.qcow2
40
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 458752
41
required size: 1074135040
42
fully allocated size: 1074135040
43
44
+== qcow2 input image and LUKS encryption ==
45
+
46
+required size: 2686976
47
+fully allocated size: 1076232192
48
+
49
== qcow2 input image and preallocation (human) ==
50
51
required size: 1074135040
52
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 524288
53
required size: 1074135040
54
fully allocated size: 1074135040
55
56
+== raw input image and LUKS encryption ==
57
+
58
+required size: 2686976
59
+fully allocated size: 1076232192
60
+
61
== raw input image and preallocation (human) ==
62
63
required size: 1074135040
64
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 458752
65
"fully-allocated": 1074135040
66
}
67
68
+== qcow2 input image and LUKS encryption ==
69
+
70
+{
71
+ "required": 2686976,
72
+ "fully-allocated": 1076232192
73
+}
74
+
75
== qcow2 input image and preallocation (json) ==
76
77
{
78
@@ -XXX,XX +XXX,XX @@ converted image file size in bytes: 524288
79
"fully-allocated": 1074135040
80
}
81
82
+== raw input image and LUKS encryption ==
83
+
84
+{
85
+ "required": 2686976,
86
+ "fully-allocated": 1076232192
87
+}
88
+
89
== raw input image and preallocation (json) ==
90
91
{
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
From: yuchenlin <yuchenlin@synology.com>
2
1
3
In vmdk_co_create_opts, when it finds hw_version is undefined, it will
4
set it to 4, which misleading the compat6 and hwversion in
5
vmdk_co_do_create. Simply set hw_version to NULL after free, let
6
the logic in vmdk_co_do_create to decide the value of hw_version.
7
8
This bug can be reproduced by:
9
10
$ qemu-img convert -O vmdk -o subformat=streamOptimized,compat6
11
/home/yuchenlin/syno.qcow2 /home/yuchenlin/syno.vmdk
12
13
qemu-img: /home/yuchenlin/syno.vmdk: error while converting vmdk:
14
compat6 cannot be enabled with hwversion set
15
16
Signed-off-by: yuchenlin <yuchenlin@synology.com>
17
Message-id: 20190221110805.28239-1-yuchenlin@synology.com
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block/vmdk.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
22
23
diff --git a/block/vmdk.c b/block/vmdk.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/vmdk.c
26
+++ b/block/vmdk.c
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts *opts
28
compat6 = qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false);
29
if (strcmp(hw_version, "undefined") == 0) {
30
g_free(hw_version);
31
- hw_version = g_strdup("4");
32
+ hw_version = NULL;
33
}
34
fmt = qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT);
35
zeroed_grain = qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib