1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
1
The following changes since commit 59a568b57848b10e8a44518a889323f12ccdd8f4:
2
2
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +0000)
3
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190222-pull-request' into staging (2019-02-25 12:49:07 +0000)
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 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
9
for you to fetch changes up to 1b967e9f348d48788a2ab481d45398b80ce71fa6:
10
10
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block (2019-02-25 15:16:57 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- auto-read-only option to fix commit job when used with -blockdev
16
- Block graph change fixes (avoid loops, cope with non-tree graphs)
17
- Fix help text related qemu-iotests failure (by improving the help text
17
- bdrv_set_aio_context() related fixes
18
and updating the reference output)
18
- HMP snapshot commands: Use only tag, not the ID to identify snapshots
19
- quorum: Add missing checks when adding/removing child nodes
19
- qmeu-img, commit: Error path fixes
20
- Don't take address of fields in packed structs
20
- block/nvme: Build fix for gcc 9
21
- vvfat: Fix crash when reporting error about too many files in directory
21
- MAINTAINERS updates
22
- Fix various issues with bdrv_refresh_filename()
23
- Fix various iotests
24
- Include LUKS overhead in qemu-img measure for qcow2
25
- A fix for vmdk's image creation interface
22
26
23
----------------------------------------------------------------
27
----------------------------------------------------------------
24
Alberto Garcia (7):
28
Alberto Garcia (2):
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
29
commit: Replace commit_top_bs on failure after deleting the block job
26
qcow2: Get the request alignment for encrypted images from QCryptoBlock
30
qcow2: Assert that L2 table offsets fit in the L1 table
27
quorum: Remove quorum_err()
31
28
quorum: Return an error if the blkverify mode has invalid settings
32
Daniel Henrique Barboza (3):
29
iotest: Test the blkverify mode of the Quorum driver
33
block/snapshot.c: eliminate use of ID input in snapshot operations
30
quorum: Forbid adding children in blkverify mode
34
block/snapshot: remove bdrv_snapshot_delete_by_id_or_name
31
iotest: Test x-blockdev-change on a Quorum
35
qcow2-snapshot: remove redundant find_snapshot_by_id_and_name call
32
33
Cleber Rosa (1):
34
iotests: make 083 specific to raw
35
36
36
Daniel P. Berrangé (1):
37
Daniel P. Berrangé (1):
37
crypto: initialize sector size even when opening with no IO flag
38
qemu-img: fix error reporting for -object
38
39
39
Kevin Wolf (12):
40
Denis Plotnikov (1):
40
vpc: Don't leak opts in vpc_open()
41
block: don't set the same context
41
block: Update flags in bdrv_set_read_only()
42
42
block: Add auto-read-only option
43
Jeff Cody (2):
43
rbd: Close image in qemu_rbd_open() error path
44
MAINTAINERS: Replace myself with John Snow for block jobs
44
block: Require auto-read-only for existing fallbacks
45
MAINTAINERS: Remove myself as block maintainer
45
nbd: Support auto-read-only option
46
46
file-posix: Support auto-read-only option
47
Kevin Wolf (14):
47
curl: Support auto-read-only option
48
block-backend: Make blk_inc/dec_in_flight public
48
gluster: Support auto-read-only option
49
virtio-blk: Increase in_flight for request restart BH
49
iscsi: Support auto-read-only option
50
nbd: Restrict connection_co reentrance
50
block: Make auto-read-only=on default for -drive
51
io: Make qio_channel_yield() interruptible
51
qemu-iotests: Test auto-read-only with -drive and -blockdev
52
io: Remove redundant read/write_coroutine assignments
52
53
nbd: Move nbd_read_eof() to nbd/client.c
53
Leonid Bloch (2):
54
nbd: Use low-level QIOChannel API in nbd_read_eof()
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
55
nbd: Increase bs->in_flight during AioContext switch
55
include: Add a comment to explain the origin of sizes' lookup table
56
block: Don't poll in bdrv_set_aio_context()
56
57
block: Fix AioContext switch for drained node
57
Li Qiang (1):
58
test-bdrv-drain: AioContext switch in drained section
58
block: change some function return type to bool
59
block: Use normal drain for bdrv_set_aio_context()
59
60
aio-posix: Assert that aio_poll() is always called in home thread
60
Max Reitz (5):
61
Merge remote-tracking branch 'mreitz/tags/pull-block-2019-02-25' into queue-block
61
option: Make option help nicer to read
62
62
chardev: Indent list of chardevs
63
Max Reitz (42):
63
qdev-monitor: Make device options help nicer
64
block: Use bdrv_refresh_filename() to pull
64
object: Make option help nicer to read
65
block: Use children list in bdrv_refresh_filename
65
fw_cfg: Drop newline in @file description
66
block: Skip implicit nodes for filename info
66
67
block: Add BDS.auto_backing_file
67
Peter Maydell (5):
68
block: Respect backing bs in bdrv_refresh_filename
68
block/qcow2: Don't take address of fields in packed structs
69
iotests.py: Add filter_imgfmt()
69
block/qcow: Don't take address of fields in packed structs
70
iotests.py: Add node_info()
70
block/qcow2-bitmap: Don't take address of fields in packed structs
71
iotests: Add test for backing file overrides
71
block/vhdx: Don't take address of fields in packed structs
72
block: Make path_combine() return the path
72
block/vdi: Don't take address of fields in packed structs
73
block: bdrv_get_full_backing_filename_from_...'s ret. val.
73
74
block: bdrv_get_full_backing_filename's ret. val.
74
Stefan Weil (1):
75
block: Add bdrv_make_absolute_filename()
75
qemu-io-cmds: Fix two format strings
76
block: Fix bdrv_find_backing_image()
77
block: Add bdrv_dirname()
78
blkverify: Make bdrv_dirname() return NULL
79
quorum: Make bdrv_dirname() return NULL
80
block/nbd: Make bdrv_dirname() return NULL
81
block/nfs: Implement bdrv_dirname()
82
block: Use bdrv_dirname() for relative filenames
83
iotests: Add quorum case to test 110
84
block: Add strong_runtime_opts to BlockDriver
85
block: Add BlockDriver.bdrv_gather_child_options
86
block: Generically refresh runtime options
87
block: Purify .bdrv_refresh_filename()
88
block: Do not copy exact_filename from format file
89
block/nvme: Fix bdrv_refresh_filename()
90
block/curl: Harmonize option defaults
91
block/curl: Implement bdrv_refresh_filename()
92
block/null: Generate filename even with latency-ns
93
block: BDS options may lack the "driver" option
94
iotests: Test json:{} filenames of internal BDSs
95
iotests: Re-add filename filters
96
iotests: Fix 237 for Python 2.x
97
iotests: Remove superfluous rm from 232
98
iotests: Fix 232 for LUKS
99
iotests: Fix 207 to use QMP filters for qmp_log
100
iotests.py: Add is_str()
101
iotests.py: Filter filename in any string value
102
iotests: Filter SSH paths
103
iotests: Let 045 be run concurrently
104
iotests.py: s/_/-/g on keys in qmp_log()
105
iotests: Skip 211 on insufficient memory
106
107
Stefan Hajnoczi (2):
108
qcow2: include LUKS payload overhead in qemu-img measure
109
iotests: add LUKS payload overhead to 178 qemu-img measure test
76
110
77
Thomas Huth (1):
111
Thomas Huth (1):
78
block/vvfat: Fix crash when reporting error about too many files in directory
112
block/nvme: Remove QEMU_PACKED from naturally aligned NVMeRegs struct
79
113
80
qapi/block-core.json | 7 +
114
Vladimir Sementsov-Ogievskiy (3):
81
block/vhdx.h | 12 +-
115
block: improve should_update_child
82
include/block/block.h | 5 +-
116
block: fix bdrv_check_perm for non-tree subgraph
83
include/qemu/option.h | 2 +-
117
tests: add test-bdrv-graph-mod
84
include/qemu/units.h | 18 +
118
85
include/sysemu/block-backend.h | 6 +-
119
yuchenlin (1):
86
block.c | 60 ++-
120
vmdk: false positive of compat6 with hwversion not set
87
block/block-backend.c | 8 +-
121
88
block/bochs.c | 17 +-
122
block/nbd-client.h | 1 +
89
block/cloop.c | 16 +-
123
include/block/block.h | 16 +-
90
block/curl.c | 8 +-
124
include/block/block_int.h | 53 +++-
91
block/dmg.c | 16 +-
125
include/block/nbd.h | 3 +-
92
block/file-posix.c | 19 +-
126
include/block/snapshot.h | 3 -
93
block/gluster.c | 12 +-
127
include/io/channel.h | 9 +-
94
block/iscsi.c | 8 +-
128
include/sysemu/block-backend.h | 2 +
95
block/nbd-client.c | 10 +-
129
nbd/nbd-internal.h | 19 --
96
block/qcow.c | 18 +-
130
block.c | 597 +++++++++++++++++++++++++++------------
97
block/qcow2-bitmap.c | 24 +-
131
block/blkdebug.c | 70 ++---
98
block/qcow2.c | 66 +--
132
block/blklogwrites.c | 33 +--
99
block/quorum.c | 45 +-
133
block/blkverify.c | 29 +-
100
block/rbd.c | 14 +-
134
block/block-backend.c | 4 +-
101
block/vdi.c | 68 +--
135
block/commit.c | 7 +-
102
block/vhdx-endian.c | 118 ++---
136
block/crypto.c | 8 +
103
block/vhdx-log.c | 4 +-
137
block/curl.c | 55 +++-
104
block/vhdx.c | 18 +-
138
block/gluster.c | 19 ++
105
block/vpc.c | 2 +
139
block/iscsi.c | 18 ++
106
block/vvfat.c | 15 +-
140
block/mirror.c | 3 +-
107
blockdev.c | 3 +-
141
block/nbd-client.c | 36 ++-
108
chardev/char.c | 2 +-
142
block/nbd.c | 46 +--
109
crypto/block-qcow.c | 2 +
143
block/nfs.c | 54 ++--
110
qdev-monitor.c | 13 +-
144
block/null.c | 32 ++-
111
qemu-img.c | 4 +-
145
block/nvme.c | 29 +-
112
qemu-io-cmds.c | 4 +-
146
block/qapi.c | 16 +-
113
util/qemu-option.c | 32 +-
147
block/qcow.c | 14 +-
114
vl.c | 15 +-
148
block/qcow2-cluster.c | 3 +
115
tests/qemu-iotests/081 | 116 +++++
149
block/qcow2-snapshot.c | 5 -
116
tests/qemu-iotests/081.out | 70 +++
150
block/qcow2.c | 89 +++++-
117
tests/qemu-iotests/082.out | 956 ++++++++++++++++++++---------------------
151
block/qed.c | 7 +-
118
tests/qemu-iotests/083 | 2 +-
152
block/quorum.c | 71 +++--
119
tests/qemu-iotests/232 | 147 +++++++
153
block/raw-format.c | 11 +-
120
tests/qemu-iotests/232.out | 59 +++
154
block/rbd.c | 14 +
121
tests/qemu-iotests/group | 1 +
155
block/replication.c | 10 +-
122
42 files changed, 1266 insertions(+), 776 deletions(-)
156
block/sheepdog.c | 12 +
123
create mode 100755 tests/qemu-iotests/232
157
block/snapshot.c | 25 +-
124
create mode 100644 tests/qemu-iotests/232.out
158
block/ssh.c | 12 +
125
159
block/throttle.c | 7 +
160
block/vhdx-log.c | 1 +
161
block/vmdk.c | 46 ++-
162
block/vpc.c | 7 +
163
block/vvfat.c | 12 +
164
block/vxhs.c | 11 +
165
blockdev.c | 8 +
166
hw/block/virtio-blk.c | 4 +
167
io/channel.c | 22 +-
168
nbd/client.c | 52 +++-
169
qemu-img.c | 64 +++--
170
tests/test-bdrv-drain.c | 32 +++
171
tests/test-bdrv-graph-mod.c | 198 +++++++++++++
172
util/aio-posix.c | 3 +-
173
MAINTAINERS | 22 +-
174
hmp-commands.hx | 32 ++-
175
scripts/qemu.py | 5 +-
176
tests/Makefile.include | 2 +
177
tests/qemu-iotests/045 | 2 +-
178
tests/qemu-iotests/051.out | 8 +-
179
tests/qemu-iotests/051.pc.out | 8 +-
180
tests/qemu-iotests/110 | 29 +-
181
tests/qemu-iotests/110.out | 9 +-
182
tests/qemu-iotests/178 | 8 +
183
tests/qemu-iotests/178.out.qcow2 | 24 ++
184
tests/qemu-iotests/206.out | 56 ++--
185
tests/qemu-iotests/207 | 10 +-
186
tests/qemu-iotests/207.out | 18 +-
187
tests/qemu-iotests/210 | 5 +-
188
tests/qemu-iotests/210.out | 28 +-
189
tests/qemu-iotests/211 | 9 +-
190
tests/qemu-iotests/211.out | 26 +-
191
tests/qemu-iotests/212 | 5 +-
192
tests/qemu-iotests/212.out | 44 +--
193
tests/qemu-iotests/213 | 5 +-
194
tests/qemu-iotests/213.out | 46 +--
195
tests/qemu-iotests/224 | 139 +++++++++
196
tests/qemu-iotests/224.out | 18 ++
197
tests/qemu-iotests/228 | 239 ++++++++++++++++
198
tests/qemu-iotests/228.out | 84 ++++++
199
tests/qemu-iotests/232 | 5 +-
200
tests/qemu-iotests/237 | 7 +-
201
tests/qemu-iotests/237.out | 54 ++--
202
tests/qemu-iotests/common.rc | 1 +
203
tests/qemu-iotests/group | 2 +
204
tests/qemu-iotests/iotests.py | 36 ++-
205
83 files changed, 2191 insertions(+), 697 deletions(-)
206
create mode 100644 tests/test-bdrv-graph-mod.c
207
create mode 100755 tests/qemu-iotests/224
208
create mode 100644 tests/qemu-iotests/224.out
209
create mode 100755 tests/qemu-iotests/228
210
create mode 100644 tests/qemu-iotests/228.out
211
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
1
From: Jeff Cody <jcody@redhat.com>
2
2
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
3
I'll not be involved with day-to-day qemu development, and John
4
it will be embedded as a literal expression in the binary (as the
4
Snow is a block jobs wizard. Have him take over block job
5
default value) because it is stringified to mark the size of the default
5
maintainership duties.
6
value. Now this is fixed by using a defined number to define this value.
7
6
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
11
---
12
block/vdi.c | 4 ++--
12
MAINTAINERS | 4 ++--
13
1 file changed, 2 insertions(+), 2 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
14
14
15
diff --git a/block/vdi.c b/block/vdi.c
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/vdi.c
17
--- a/MAINTAINERS
18
+++ b/block/vdi.c
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ F: include/scsi/*
20
#define BLOCK_OPT_STATIC "static"
20
F: scsi/*
21
21
22
#define SECTOR_SIZE 512
22
Block Jobs
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
23
-M: Jeff Cody <jcody@redhat.com>
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
24
+M: John Snow <jsnow@redhat.com>
25
25
L: qemu-block@nongnu.org
26
#if defined(CONFIG_VDI_DEBUG)
26
S: Supported
27
#define VDI_DEBUG 1
27
F: blockjob.c
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
28
@@ -XXX,XX +XXX,XX @@ F: block/commit.c
29
goto fail;
29
F: block/stream.c
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
30
F: block/mirror.c
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
31
F: qapi/job.json
32
- " is not %" PRIu64 ")",
32
-T: git https://github.com/codyprime/qemu-kvm-jtc.git block
33
+ " is not %" PRIu32 ")",
33
+T: git https://github.com/jnsnow/qemu.git jobs
34
header.block_size, DEFAULT_CLUSTER_SIZE);
34
35
ret = -ENOTSUP;
35
Block QAPI, monitor, command line
36
goto fail;
36
M: Markus Armbruster <armbru@redhat.com>
37
--
37
--
38
2.19.1
38
2.20.1
39
39
40
40
diff view generated by jsdifflib
New patch
1
From: Jeff Cody <jcody@redhat.com>
1
2
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
New patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
2
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
From: Stefan Weil <sw@weilnetz.de>
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
2
2
3
Use %zu instead of %zd for unsigned numbers.
3
After the previous patch, the only instance of this function left
4
is inside qemu-img.c.
4
5
5
This fixes two error messages from the LSTM static code analyzer:
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:
6
13
7
This argument should be of type 'ssize_t' but is of type 'unsigned long'
14
pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
8
15
9
Signed-off-by: Stefan Weil <sw@weilnetz.de>
16
Based on that, it is unlikely that "snapshot_name" might contain
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
27
---
13
qemu-io-cmds.c | 4 ++--
28
include/block/snapshot.h | 3 ---
14
1 file changed, 2 insertions(+), 2 deletions(-)
29
block/snapshot.c | 20 --------------------
30
qemu-img.c | 15 +++++++++++----
31
3 files changed, 11 insertions(+), 27 deletions(-)
15
32
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
33
diff --git a/include/block/snapshot.h b/include/block/snapshot.h
17
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
18
--- a/qemu-io-cmds.c
35
--- a/include/block/snapshot.h
19
+++ b/qemu-io-cmds.c
36
+++ b/include/block/snapshot.h
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
37
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
21
memset(cmp_buf, pattern, qiov.size);
38
const char *snapshot_id,
22
if (memcmp(buf, cmp_buf, qiov.size)) {
39
const char *name,
23
printf("Pattern verification failed at offset %"
40
Error **errp);
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
41
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
42
- const char *id_or_name,
26
ret = -EINVAL;
43
- Error **errp);
44
int bdrv_snapshot_list(BlockDriverState *bs,
45
QEMUSnapshotInfo **psn_info);
46
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
47
diff --git a/block/snapshot.c b/block/snapshot.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/snapshot.c
50
+++ b/block/snapshot.c
51
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_delete(BlockDriverState *bs,
52
return ret;
53
}
54
55
-int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
56
- const char *id_or_name,
57
- Error **errp)
58
-{
59
- int ret;
60
- Error *local_err = NULL;
61
-
62
- ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
63
- if (ret == -ENOENT || ret == -EINVAL) {
64
- error_free(local_err);
65
- local_err = NULL;
66
- ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
67
- }
68
-
69
- if (ret < 0) {
70
- error_propagate(errp, local_err);
71
- }
72
- return ret;
73
-}
74
-
75
int bdrv_snapshot_list(BlockDriverState *bs,
76
QEMUSnapshotInfo **psn_info)
77
{
78
diff --git a/qemu-img.c b/qemu-img.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/qemu-img.c
81
+++ b/qemu-img.c
82
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
83
break;
84
85
case SNAPSHOT_DELETE:
86
- bdrv_snapshot_delete_by_id_or_name(bs, snapshot_name, &err);
87
- if (err) {
88
- error_reportf_err(err, "Could not delete snapshot '%s': ",
89
- snapshot_name);
90
+ ret = bdrv_snapshot_find(bs, &sn, snapshot_name);
91
+ if (ret < 0) {
92
+ error_report("Could not delete snapshot '%s': snapshot not "
93
+ "found", snapshot_name);
94
ret = 1;
95
+ } else {
96
+ ret = bdrv_snapshot_delete(bs, sn.id_str, sn.name, &err);
97
+ if (ret < 0) {
98
+ error_reportf_err(err, "Could not delete snapshot '%s': ",
99
+ snapshot_name);
100
+ ret = 1;
101
+ }
27
}
102
}
28
g_free(cmp_buf);
103
break;
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
32
printf("Pattern verification failed at offset %"
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
35
}
36
g_free(cmp_buf);
37
}
104
}
38
--
105
--
39
2.19.1
106
2.20.1
40
107
41
108
diff view generated by jsdifflib
New patch
1
From: Daniel Henrique Barboza <danielhb413@gmail.com>
1
2
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: Alberto Garcia <berto@igalia.com>
1
From: Denis Plotnikov <dplotnikov@virtuozzo.com>
2
2
3
The blkverify mode of Quorum only works when the number of children is
3
Adds a fast path on aio context setting preventing
4
exactly two, so any attempt to add a new one must return an error.
4
unnecessary context setting routine.
5
Also, it prevents issues with cyclic walk of child
6
bds-es appeared because of registering aio walking
7
notifiers:
5
8
6
quorum_del_child() on the other hand doesn't need any additional check
9
Call stack:
7
because decreasing the number of children would make it go under the
8
vote threshold.
9
10
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
0 __GI_raise
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
12
1 __GI_abort
13
2 __assert_fail_base
14
3 __GI___assert_fail
15
4 bdrv_detach_aio_context (bs=0x55f54d65c000) <<<
16
5 bdrv_detach_aio_context (bs=0x55f54fc8a800)
17
6 bdrv_set_aio_context (bs=0x55f54fc8a800, ...)
18
7 block_job_attached_aio_context
19
8 bdrv_attach_aio_context (bs=0x55f54d65c000, ...) <<<
20
9 bdrv_set_aio_context (bs=0x55f54d65c000)
21
10 blk_set_aio_context
22
11 virtio_blk_data_plane_stop
23
12 virtio_bus_stop_ioeventfd
24
13 virtio_vmstate_change
25
14 vm_state_notify (running=0, state=RUN_STATE_SHUTDOWN)
26
15 do_vm_stop (state=RUN_STATE_SHUTDOWN, send_stop=true)
27
16 vm_stop (state=RUN_STATE_SHUTDOWN)
28
17 main_loop_should_exit
29
18 main_loop
30
19 main
31
32
This can happen because of "new" context attachment to VM disk bds.
33
When attaching a new context the corresponding aio context handler is
34
called for each of aio_notifiers registered on the VM disk bds context.
35
Among those handlers, there is the block_job_attached_aio_context handler
36
which sets a new aio context for the block job bds. When doing so,
37
the old context is detached from all the block job bds children and one of
38
them is the VM disk bds, serving as backing store for the blockjob bds,
39
although the VM disk bds is actually the initializer of that process.
40
Since the VM disk bds is protected with walking_aio_notifiers flag
41
from double processing in recursive calls, the assert fires.
42
43
Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
44
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
45
---
14
block/quorum.c | 8 ++++++++
46
block.c | 4 ++++
15
1 file changed, 8 insertions(+)
47
1 file changed, 4 insertions(+)
16
48
17
diff --git a/block/quorum.c b/block/quorum.c
49
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
51
--- a/block.c
20
+++ b/block/quorum.c
52
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
53
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
22
char indexstr[32];
54
{
23
int ret;
55
AioContext *ctx = bdrv_get_aio_context(bs);
24
56
25
+ if (s->is_blkverify) {
57
+ if (ctx == new_context) {
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
27
+ return;
58
+ return;
28
+ }
59
+ }
29
+
60
+
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
61
aio_disable_external(ctx);
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
62
bdrv_parent_drained_begin(bs, NULL, false);
32
s->next_child_index == UINT_MAX) {
63
bdrv_drain(bs); /* ensure there are no in-flight requests */
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
34
return;
35
}
36
37
+ /* We know now that num_children > threshold, so blkverify must be false */
38
+ assert(!s->is_blkverify);
39
+
40
bdrv_drained_begin(bs);
41
42
/* We can safely remove this child now */
43
--
64
--
44
2.19.1
65
2.20.1
45
66
46
67
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This patch tests that you can add and remove drives from a Quorum
3
If there's an error in commit_start() then the block job must be
4
using the x-blockdev-change command.
4
deleted before replacing commit_top_bs, otherwise it will fail because
5
of lack of permissions. This happens since the permission system was
6
introduced in 8dfba2797761d8a43744e4e6571c8175e448a478.
7
8
Fortunately this bug doesn't seem to be possible to reproduce at the
9
moment without changing the code.
5
10
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
13
---
9
tests/qemu-iotests/081 | 86 ++++++++++++++++++++++++++++++++++++++
14
block/commit.c | 4 +++-
10
tests/qemu-iotests/081.out | 54 ++++++++++++++++++++++++
15
1 file changed, 3 insertions(+), 1 deletion(-)
11
2 files changed, 140 insertions(+)
12
16
13
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
17
diff --git a/block/commit.c b/block/commit.c
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/081
16
+++ b/tests/qemu-iotests/081
17
@@ -XXX,XX +XXX,XX @@ quorum="$quorum,file.children.2.driver=raw"
18
19
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
20
21
+echo
22
+echo "== dynamically adding a child to a quorum =="
23
+
24
+for verify in false true; do
25
+ run_qemu <<EOF
26
+ { "execute": "qmp_capabilities" }
27
+ { "execute": "blockdev-add",
28
+ "arguments": {
29
+ "driver": "quorum",
30
+ "node-name": "drive0-quorum",
31
+ "vote-threshold": 2,
32
+ "blkverify": ${verify},
33
+ "children": [
34
+ {
35
+ "driver": "$IMGFMT",
36
+ "file": {
37
+ "driver": "file",
38
+ "filename": "$TEST_DIR/1.raw"
39
+ }
40
+ },
41
+ {
42
+ "driver": "$IMGFMT",
43
+ "file": {
44
+ "driver": "file",
45
+ "filename": "$TEST_DIR/2.raw"
46
+ }
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ { "execute": "blockdev-add",
52
+ "arguments": {
53
+ "node-name": "drive3",
54
+ "driver": "$IMGFMT",
55
+ "file": {
56
+ "driver": "file",
57
+ "filename": "$TEST_DIR/2.raw"
58
+ }
59
+ }
60
+ }
61
+ { "execute": "x-blockdev-change",
62
+ "arguments": { "parent": "drive0-quorum",
63
+ "node": "drive3" } }
64
+ { "execute": "quit" }
65
+EOF
66
+done
67
+
68
+echo
69
+echo "== dynamically removing a child from a quorum =="
70
+
71
+for verify in false true; do
72
+ for vote_threshold in 1 2; do
73
+ run_qemu <<EOF
74
+ { "execute": "qmp_capabilities" }
75
+ { "execute": "blockdev-add",
76
+ "arguments": {
77
+ "driver": "quorum",
78
+ "node-name": "drive0-quorum",
79
+ "vote-threshold": ${vote_threshold},
80
+ "blkverify": ${verify},
81
+ "children": [
82
+ {
83
+ "driver": "$IMGFMT",
84
+ "file": {
85
+ "driver": "file",
86
+ "filename": "$TEST_DIR/1.raw"
87
+ }
88
+ },
89
+ {
90
+ "driver": "$IMGFMT",
91
+ "file": {
92
+ "driver": "file",
93
+ "filename": "$TEST_DIR/2.raw"
94
+ }
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ { "execute": "x-blockdev-change",
100
+ "arguments": { "parent": "drive0-quorum",
101
+ "child": "children.1" } }
102
+ { "execute": "quit" }
103
+EOF
104
+ done
105
+done
106
+
107
# success, all done
108
echo "*** done"
109
rm -f $seq.full
110
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
111
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/081.out
19
--- a/block/commit.c
113
+++ b/tests/qemu-iotests/081.out
20
+++ b/block/commit.c
114
@@ -XXX,XX +XXX,XX @@ read 10485760/10485760 bytes at offset 0
21
@@ -XXX,XX +XXX,XX @@ fail:
115
22
if (s->top) {
116
== checking the blkverify mode with invalid settings ==
23
blk_unref(s->top);
117
can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
24
}
118
+
25
+ job_early_fail(&s->common.job);
119
+== dynamically adding a child to a quorum ==
26
+ /* commit_top_bs has to be replaced after deleting the block job,
120
+Testing:
27
+ * otherwise this would fail because of lack of permissions. */
121
+QMP_VERSION
28
if (commit_top_bs) {
122
+{"return": {}}
29
bdrv_replace_node(commit_top_bs, top, &error_abort);
123
+{"return": {}}
30
}
124
+{"return": {}}
31
- job_early_fail(&s->common.job);
125
+{"return": {}}
32
}
126
+{"return": {}}
33
127
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
34
128
+
129
+Testing:
130
+QMP_VERSION
131
+{"return": {}}
132
+{"return": {}}
133
+{"return": {}}
134
+{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
135
+{"return": {}}
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
137
+
138
+
139
+== dynamically removing a child from a quorum ==
140
+Testing:
141
+QMP_VERSION
142
+{"return": {}}
143
+{"return": {}}
144
+{"return": {}}
145
+{"return": {}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
147
+
148
+Testing:
149
+QMP_VERSION
150
+{"return": {}}
151
+{"return": {}}
152
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
153
+{"return": {}}
154
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
155
+
156
+Testing:
157
+QMP_VERSION
158
+{"return": {}}
159
+{"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}}
160
+{"error": {"class": "GenericError", "desc": "Cannot find device=drive0-quorum nor node_name=drive0-quorum"}}
161
+{"return": {}}
162
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
163
+
164
+Testing:
165
+QMP_VERSION
166
+{"return": {}}
167
+{"return": {}}
168
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
169
+{"return": {}}
170
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
171
+
172
*** done
173
--
35
--
174
2.19.1
36
2.20.1
175
37
176
38
diff view generated by jsdifflib
1
From: Daniel P. Berrangé <berrange@redhat.com>
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
2
3
The qcow2 block driver expects to see a valid sector size even when it
3
Error reporting for user_creatable_add_opts_foreach was changed so that
4
has opened the crypto layer with QCRYPTO_BLOCK_OPEN_NO_IO.
4
it no longer called 'error_report_err' in:
5
6
commit 7e1e0c11127bde81cff260fc6859690435c509d6
7
Author: Markus Armbruster <armbru@redhat.com>
8
Date: Wed Oct 17 10:26:43 2018 +0200
9
10
qom: Clean up error reporting in user_creatable_add_opts_foreach()
11
12
Some callers were updated to pass in "&error_fatal" but all the ones in
13
qemu-img were left passing NULL. As a result all errors went to
14
/dev/null instead of being reported to the user.
5
15
6
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.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>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
21
---
10
crypto/block-qcow.c | 2 ++
22
qemu-img.c | 26 +++++++++++++-------------
11
1 file changed, 2 insertions(+)
23
1 file changed, 13 insertions(+), 13 deletions(-)
12
24
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
25
diff --git a/qemu-img.c b/qemu-img.c
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/crypto/block-qcow.c
27
--- a/qemu-img.c
16
+++ b/crypto/block-qcow.c
28
+++ b/qemu-img.c
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
29
@@ -XXX,XX +XXX,XX @@ static int img_create(int argc, char **argv)
18
Error **errp)
30
19
{
31
if (qemu_opts_foreach(&qemu_object_opts,
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
32
user_creatable_add_opts_foreach,
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
33
- NULL, NULL)) {
22
+ block->payload_offset = 0;
34
+ NULL, &error_fatal)) {
23
return 0;
35
goto fail;
24
} else {
36
}
25
if (!options->u.qcow.key_secret) {
37
38
@@ -XXX,XX +XXX,XX @@ static int img_check(int argc, char **argv)
39
40
if (qemu_opts_foreach(&qemu_object_opts,
41
user_creatable_add_opts_foreach,
42
- NULL, NULL)) {
43
+ NULL, &error_fatal)) {
44
return 1;
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv)
48
49
if (qemu_opts_foreach(&qemu_object_opts,
50
user_creatable_add_opts_foreach,
51
- NULL, NULL)) {
52
+ NULL, &error_fatal)) {
53
return 1;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
57
58
if (qemu_opts_foreach(&qemu_object_opts,
59
user_creatable_add_opts_foreach,
60
- NULL, NULL)) {
61
+ NULL, &error_fatal)) {
62
ret = 2;
63
goto out4;
64
}
65
@@ -XXX,XX +XXX,XX @@ static int img_convert(int argc, char **argv)
66
67
if (qemu_opts_foreach(&qemu_object_opts,
68
user_creatable_add_opts_foreach,
69
- NULL, NULL)) {
70
+ NULL, &error_fatal)) {
71
goto fail_getopt;
72
}
73
74
@@ -XXX,XX +XXX,XX @@ static int img_info(int argc, char **argv)
75
76
if (qemu_opts_foreach(&qemu_object_opts,
77
user_creatable_add_opts_foreach,
78
- NULL, NULL)) {
79
+ NULL, &error_fatal)) {
80
return 1;
81
}
82
83
@@ -XXX,XX +XXX,XX @@ static int img_map(int argc, char **argv)
84
85
if (qemu_opts_foreach(&qemu_object_opts,
86
user_creatable_add_opts_foreach,
87
- NULL, NULL)) {
88
+ NULL, &error_fatal)) {
89
return 1;
90
}
91
92
@@ -XXX,XX +XXX,XX @@ static int img_snapshot(int argc, char **argv)
93
94
if (qemu_opts_foreach(&qemu_object_opts,
95
user_creatable_add_opts_foreach,
96
- NULL, NULL)) {
97
+ NULL, &error_fatal)) {
98
return 1;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
102
103
if (qemu_opts_foreach(&qemu_object_opts,
104
user_creatable_add_opts_foreach,
105
- NULL, NULL)) {
106
+ NULL, &error_fatal)) {
107
return 1;
108
}
109
110
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
111
112
if (qemu_opts_foreach(&qemu_object_opts,
113
user_creatable_add_opts_foreach,
114
- NULL, NULL)) {
115
+ NULL, &error_fatal)) {
116
return 1;
117
}
118
119
@@ -XXX,XX +XXX,XX @@ static int img_amend(int argc, char **argv)
120
121
if (qemu_opts_foreach(&qemu_object_opts,
122
user_creatable_add_opts_foreach,
123
- NULL, NULL)) {
124
+ NULL, &error_fatal)) {
125
ret = -1;
126
goto out_no_progress;
127
}
128
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
129
130
if (qemu_opts_foreach(&qemu_object_opts,
131
user_creatable_add_opts_foreach,
132
- NULL, NULL)) {
133
+ NULL, &error_fatal)) {
134
ret = -1;
135
goto out;
136
}
137
@@ -XXX,XX +XXX,XX @@ static int img_measure(int argc, char **argv)
138
139
if (qemu_opts_foreach(&qemu_object_opts,
140
user_creatable_add_opts_foreach,
141
- NULL, NULL)) {
142
+ NULL, &error_fatal)) {
143
goto out;
144
}
145
26
--
146
--
27
2.19.1
147
2.20.1
28
148
29
149
diff view generated by jsdifflib
1
From: Li Qiang <liq3ea@163.com>
1
For some users of BlockBackends, just increasing the in_flight counter
2
is easier than implementing separate handlers in BlockDevOps. Make the
3
helper functions for this public.
2
4
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
6
---
7
include/sysemu/block-backend.h | 6 +++---
7
include/sysemu/block-backend.h | 2 ++
8
block/block-backend.c | 8 ++++----
8
block/block-backend.c | 4 ++--
9
2 files changed, 7 insertions(+), 7 deletions(-)
9
2 files changed, 4 insertions(+), 2 deletions(-)
10
10
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/sysemu/block-backend.h
13
--- a/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
14
+++ b/include/sysemu/block-backend.h
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
15
@@ -XXX,XX +XXX,XX @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
16
int error);
16
int blk_co_flush(BlockBackend *blk);
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
17
int blk_flush(BlockBackend *blk);
18
bool is_read, int error);
18
int blk_commit_all(void);
19
-int blk_is_read_only(BlockBackend *blk);
19
+void blk_inc_in_flight(BlockBackend *blk);
20
-int blk_is_sg(BlockBackend *blk);
20
+void blk_dec_in_flight(BlockBackend *blk);
21
-int blk_enable_write_cache(BlockBackend *blk);
21
void blk_drain(BlockBackend *blk);
22
+bool blk_is_read_only(BlockBackend *blk);
22
void blk_drain_all(void);
23
+bool blk_is_sg(BlockBackend *blk);
23
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
24
+bool blk_enable_write_cache(BlockBackend *blk);
25
void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
26
void blk_invalidate_cache(BlockBackend *blk, Error **errp);
27
bool blk_is_inserted(BlockBackend *blk);
28
diff --git a/block/block-backend.c b/block/block-backend.c
24
diff --git a/block/block-backend.c b/block/block-backend.c
29
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-backend.c
26
--- a/block/block-backend.c
31
+++ b/block/block-backend.c
27
+++ b/block/block-backend.c
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
28
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
33
}
29
return bdrv_make_zero(blk->root, flags);
34
}
30
}
35
31
36
-int blk_is_read_only(BlockBackend *blk)
32
-static void blk_inc_in_flight(BlockBackend *blk)
37
+bool blk_is_read_only(BlockBackend *blk)
33
+void blk_inc_in_flight(BlockBackend *blk)
38
{
34
{
39
BlockDriverState *bs = blk_bs(blk);
35
atomic_inc(&blk->in_flight);
40
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
42
}
43
}
36
}
44
37
45
-int blk_is_sg(BlockBackend *blk)
38
-static void blk_dec_in_flight(BlockBackend *blk)
46
+bool blk_is_sg(BlockBackend *blk)
39
+void blk_dec_in_flight(BlockBackend *blk)
47
{
40
{
48
BlockDriverState *bs = blk_bs(blk);
41
atomic_dec(&blk->in_flight);
49
42
aio_wait_kick();
50
if (!bs) {
51
- return 0;
52
+ return false;
53
}
54
55
return bdrv_is_sg(bs);
56
}
57
58
-int blk_enable_write_cache(BlockBackend *blk)
59
+bool blk_enable_write_cache(BlockBackend *blk)
60
{
61
return blk->enable_write_cache;
62
}
63
--
43
--
64
2.19.1
44
2.20.1
65
45
66
46
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
virtio_blk_dma_restart_bh() submits new requests, so in order to make
2
sure that these requests are not started inside a drained section of the
3
attached BlockBackend, we need to make sure that draining the
4
BlockBackend waits for the BH to be executed.
2
5
3
Taking the address of a field in a packed struct is a bad idea, because
6
This BH is still questionable because its scheduled in the main thread
4
it might not be actually aligned enough for that pointer type (and
7
instead of the configured iothread. Leave a FIXME comment for this.
5
thus cause a crash on dereference on some host architectures). Newer
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
8
9
There are a few places where the in-place swap function is
9
But with this fix, enabling the data plane at least waits for these
10
used on something other than a packed struct field; we convert
10
requests (in bdrv_set_aio_context()) instead of changing the AioContext
11
those anyway, for consistency.
11
under their feet and making them run in the wrong thread, causing
12
crashes and failures (e.g. due to missing locking).
12
13
13
This patch was produced with the following spatch script:
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
15
---
52
block/qcow.c | 18 +++++++++---------
16
hw/block/virtio-blk.c | 4 ++++
53
1 file changed, 9 insertions(+), 9 deletions(-)
17
1 file changed, 4 insertions(+)
54
18
55
diff --git a/block/qcow.c b/block/qcow.c
19
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
56
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow.c
21
--- a/hw/block/virtio-blk.c
58
+++ b/block/qcow.c
22
+++ b/hw/block/virtio-blk.c
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
23
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
60
if (ret < 0) {
24
if (mrb.num_reqs) {
61
goto fail;
25
virtio_blk_submit_multireq(s->blk, &mrb);
62
}
26
}
63
- be32_to_cpus(&header.magic);
27
+ blk_dec_in_flight(s->conf.conf.blk);
64
- be32_to_cpus(&header.version);
28
aio_context_release(blk_get_aio_context(s->conf.conf.blk));
65
- be64_to_cpus(&header.backing_file_offset);
29
}
66
- be32_to_cpus(&header.backing_file_size);
30
67
- be32_to_cpus(&header.mtime);
31
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
68
- be64_to_cpus(&header.size);
69
- be32_to_cpus(&header.crypt_method);
70
- be64_to_cpus(&header.l1_table_offset);
71
+ header.magic = be32_to_cpu(header.magic);
72
+ header.version = be32_to_cpu(header.version);
73
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
74
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
75
+ header.mtime = be32_to_cpu(header.mtime);
76
+ header.size = be64_to_cpu(header.size);
77
+ header.crypt_method = be32_to_cpu(header.crypt_method);
78
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
79
80
if (header.magic != QCOW_MAGIC) {
81
error_setg(errp, "Image not in qcow format");
82
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
83
}
32
}
84
33
85
for(i = 0;i < s->l1_size; i++) {
34
if (!s->bh) {
86
- be64_to_cpus(&s->l1_table[i]);
35
+ /* FIXME The data plane is not started yet, so these requests are
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
36
+ * processed in the main thread. */
37
s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
38
virtio_blk_dma_restart_bh, s);
39
+ blk_inc_in_flight(s->conf.conf.blk);
40
qemu_bh_schedule(s->bh);
88
}
41
}
89
42
}
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
91
--
43
--
92
2.19.1
44
2.20.1
93
45
94
46
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the file
1
nbd_client_attach_aio_context() schedules connection_co in the new
2
read-write if we have the permissions, but instead of erroring out for
2
AioContext and this way reenters it in any arbitrary place that has
3
read-only files, just degrade to read-only.
3
yielded. We can restrict this a bit to the function call where the
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.
4
11
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
14
---
8
block/file-posix.c | 19 ++++++++++++++++---
15
block/nbd-client.h | 1 +
9
1 file changed, 16 insertions(+), 3 deletions(-)
16
block/nbd-client.c | 22 ++++++++++++++++++++++
17
2 files changed, 23 insertions(+)
10
18
11
diff --git a/block/file-posix.c b/block/file-posix.c
19
diff --git a/block/nbd-client.h b/block/nbd-client.h
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-posix.c
21
--- a/block/nbd-client.h
14
+++ b/block/file-posix.c
22
+++ b/block/nbd-client.h
15
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
23
@@ -XXX,XX +XXX,XX @@ typedef struct NBDClientSession {
16
24
17
s->fd = -1;
25
NBDClientRequest requests[MAX_NBD_REQUESTS];
18
fd = qemu_open(filename, s->open_flags, 0644);
26
NBDReply reply;
19
- if (fd < 0) {
27
+ BlockDriverState *bs;
20
- ret = -errno;
28
bool quit;
21
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
29
} NBDClientSession;
22
+ ret = fd < 0 ? -errno : 0;
30
31
diff --git a/block/nbd-client.c b/block/nbd-client.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/nbd-client.c
34
+++ b/block/nbd-client.c
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
36
Error *local_err = NULL;
37
38
while (!s->quit) {
39
+ /*
40
+ * The NBD client can only really be considered idle when it has
41
+ * yielded from qio_channel_readv_all_eof(), waiting for data. This is
42
+ * the point where the additional scheduled coroutine entry happens
43
+ * after nbd_client_attach_aio_context().
44
+ *
45
+ * Therefore we keep an additional in_flight reference all the time and
46
+ * only drop it temporarily here.
47
+ *
48
+ * FIXME This is not safe because the QIOChannel could wake up the
49
+ * coroutine for a second time; it is not prepared for coroutine
50
+ * resumption from external code.
51
+ */
52
+ bdrv_dec_in_flight(s->bs);
53
assert(s->reply.handle == 0);
54
ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
55
+ bdrv_inc_in_flight(s->bs);
23
+
56
+
24
+ if (ret == -EACCES || ret == -EROFS) {
57
if (local_err) {
25
+ /* Try to degrade to read-only, but if it doesn't work, still use the
58
trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
26
+ * normal error message. */
59
error_free(local_err);
27
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
60
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
28
+ bdrv_flags &= ~BDRV_O_RDWR;
61
29
+ raw_parse_flags(bdrv_flags, &s->open_flags);
62
s->quit = true;
30
+ assert(!(s->open_flags & O_CREAT));
63
nbd_recv_coroutines_wake_all(s);
31
+ fd = qemu_open(filename, s->open_flags);
64
+ bdrv_dec_in_flight(s->bs);
32
+ ret = fd < 0 ? -errno : 0;
33
+ }
34
+ }
35
+
65
+
36
+ if (ret < 0) {
66
s->connection_co = NULL;
37
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
67
aio_wait_kick();
38
if (ret == -EROFS) {
68
}
39
ret = -EACCES;
69
@@ -XXX,XX +XXX,XX @@ void nbd_client_attach_aio_context(BlockDriverState *bs,
40
}
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
41
--
94
--
42
2.19.1
95
2.20.1
43
96
44
97
diff view generated by jsdifflib
New patch
1
Similar to how qemu_co_sleep_ns() allows preemption from an external
2
coroutine entry, allow reentering qio_channel_yield() early.
1
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
include/io/channel.h | 9 ++++++---
7
io/channel.c | 10 ++++++++++
8
2 files changed, 16 insertions(+), 3 deletions(-)
9
10
diff --git a/include/io/channel.h b/include/io/channel.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/io/channel.h
13
+++ b/include/io/channel.h
14
@@ -XXX,XX +XXX,XX @@ void qio_channel_detach_aio_context(QIOChannel *ioc);
15
* addition, no two coroutine can be waiting on the same condition
16
* and channel at the same time.
17
*
18
- * This must only be called from coroutine context
19
+ * This must only be called from coroutine context. It is safe to
20
+ * reenter the coroutine externally while it is waiting; in this
21
+ * case the function will return even if @condition is not yet
22
+ * available.
23
*/
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
}
50
51
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
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.
2
4
3
Taking the address of a field in a packed struct is a bad idea, because
5
This does not make a difference in intermediate states because
4
it might not be actually aligned enough for that pointer type (and
6
aio_co_wake() really enters the coroutine immediately here: These
5
thus cause a crash on dereference on some host architectures). Newer
7
handlers are never run in coroutine context, and we're in the right
6
versions of clang warn about this. Avoid the bug by not using the
8
AioContext because qio_channel_attach_aio_context() asserts that the
7
"modify in place" byte swapping functions.
9
handlers are inactive.
8
10
9
There are a few places where the in-place swap function is
11
To make these conditions more obvious, assert the right AioContext.
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
12
13
This patch was produced with the following spatch script:
13
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
14
15
@@
16
expression E;
17
@@
18
-be16_to_cpus(&E);
19
+E = be16_to_cpu(E);
20
@@
21
expression E;
22
@@
23
-be32_to_cpus(&E);
24
+E = be32_to_cpu(E);
25
@@
26
expression E;
27
@@
28
-be64_to_cpus(&E);
29
+E = be64_to_cpu(E);
30
@@
31
expression E;
32
@@
33
-cpu_to_be16s(&E);
34
+E = cpu_to_be16(E);
35
@@
36
expression E;
37
@@
38
-cpu_to_be32s(&E);
39
+E = cpu_to_be32(E);
40
@@
41
expression E;
42
@@
43
-cpu_to_be64s(&E);
44
+E = cpu_to_be64(E);
45
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
48
Tested-by: John Snow <jsnow@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
---
15
---
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
16
io/channel.c | 12 ++++++------
53
1 file changed, 12 insertions(+), 12 deletions(-)
17
1 file changed, 6 insertions(+), 6 deletions(-)
54
18
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
19
diff --git a/io/channel.c b/io/channel.c
56
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow2-bitmap.c
21
--- a/io/channel.c
58
+++ b/block/qcow2-bitmap.c
22
+++ b/io/channel.c
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
23
@@ -XXX,XX +XXX,XX @@ off_t qio_channel_io_seek(QIOChannel *ioc,
60
size_t i;
61
62
for (i = 0; i < size; ++i) {
63
- cpu_to_be64s(&bitmap_table[i]);
64
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
65
}
66
}
24
}
67
25
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
26
69
}
27
-static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
70
28
-
71
for (i = 0; i < tb->size; ++i) {
29
static void qio_channel_restart_read(void *opaque)
72
- be64_to_cpus(&table[i]);
73
+ table[i] = be64_to_cpu(table[i]);
74
ret = check_table_entry(table[i], s->cluster_size);
75
if (ret < 0) {
76
goto fail;
77
@@ -XXX,XX +XXX,XX @@ fail:
78
79
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
80
{
30
{
81
- be64_to_cpus(&entry->bitmap_table_offset);
31
QIOChannel *ioc = opaque;
82
- be32_to_cpus(&entry->bitmap_table_size);
32
Coroutine *co = ioc->read_coroutine;
83
- be32_to_cpus(&entry->flags);
33
84
- be16_to_cpus(&entry->name_size);
34
- ioc->read_coroutine = NULL;
85
- be32_to_cpus(&entry->extra_data_size);
35
- qio_channel_set_aio_fd_handlers(ioc);
86
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
36
+ /* Assert that aio_co_wake() reenters the coroutine directly */
87
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
37
+ assert(qemu_get_current_aio_context() ==
88
+ entry->flags = be32_to_cpu(entry->flags);
38
+ qemu_coroutine_get_aio_context(co));
89
+ entry->name_size = be16_to_cpu(entry->name_size);
39
aio_co_wake(co);
90
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
91
}
40
}
92
41
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
42
@@ -XXX,XX +XXX,XX @@ static void qio_channel_restart_write(void *opaque)
94
{
43
QIOChannel *ioc = opaque;
95
- cpu_to_be64s(&entry->bitmap_table_offset);
44
Coroutine *co = ioc->write_coroutine;
96
- cpu_to_be32s(&entry->bitmap_table_size);
45
97
- cpu_to_be32s(&entry->flags);
46
- ioc->write_coroutine = NULL;
98
- cpu_to_be16s(&entry->name_size);
47
- qio_channel_set_aio_fd_handlers(ioc);
99
- cpu_to_be32s(&entry->extra_data_size);
48
+ /* Assert that aio_co_wake() reenters the coroutine directly */
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
49
+ assert(qemu_get_current_aio_context() ==
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
50
+ qemu_coroutine_get_aio_context(co));
102
+ entry->flags = cpu_to_be32(entry->flags);
51
aio_co_wake(co);
103
+ entry->name_size = cpu_to_be16(entry->name_size);
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
105
}
52
}
106
53
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
108
--
54
--
109
2.19.1
55
2.20.1
110
56
111
57
diff view generated by jsdifflib
1
Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
1
The only caller of nbd_read_eof() is nbd_receive_reply(), so it doesn't
2
calling rbd_open(), but neglected to close the image again in this error
2
have to live in the header file, but can move next to its caller.
3
path. The error path should contain everything that the regular close
4
function qemu_rbd_close() contains.
5
3
6
This adds the missing rbd_close() call.
4
Also add the missing coroutine_fn to the function and its caller.
7
5
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
10
---
8
---
11
block/rbd.c | 1 +
9
include/block/nbd.h | 3 ++-
12
1 file changed, 1 insertion(+)
10
nbd/nbd-internal.h | 19 -------------------
11
nbd/client.c | 22 +++++++++++++++++++++-
12
3 files changed, 23 insertions(+), 21 deletions(-)
13
13
14
diff --git a/block/rbd.c b/block/rbd.c
14
diff --git a/include/block/nbd.h b/include/block/nbd.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
16
--- a/include/block/nbd.h
17
+++ b/block/rbd.c
17
+++ b/include/block/nbd.h
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
18
@@ -XXX,XX +XXX,XX @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
19
"automatically marking the image read-only.");
19
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
20
r = bdrv_set_read_only(bs, true, &local_err);
20
Error **errp);
21
if (r < 0) {
21
int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
22
+ rbd_close(s->image);
22
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
23
error_propagate(errp, local_err);
23
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
24
goto failed_open;
24
+ Error **errp);
25
}
25
int nbd_client(int fd);
26
int nbd_disconnect(int fd);
27
int nbd_errno_to_system_errno(int err);
28
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/nbd/nbd-internal.h
31
+++ b/nbd/nbd-internal.h
32
@@ -XXX,XX +XXX,XX @@
33
#define NBD_SET_TIMEOUT _IO(0xab, 9)
34
#define NBD_SET_FLAGS _IO(0xab, 10)
35
36
-/* nbd_read_eof
37
- * Tries to read @size bytes from @ioc.
38
- * Returns 1 on success
39
- * 0 on eof, when no data was read (errp is not set)
40
- * negative errno on failure (errp is set)
41
- */
42
-static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
43
- Error **errp)
44
-{
45
- int ret;
46
-
47
- assert(size);
48
- ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
49
- if (ret < 0) {
50
- ret = -EIO;
51
- }
52
- return ret;
53
-}
54
-
55
/* nbd_write
56
* Writes @size bytes to @ioc. Returns 0 on success.
57
*/
58
diff --git a/nbd/client.c b/nbd/client.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/nbd/client.c
61
+++ b/nbd/client.c
62
@@ -XXX,XX +XXX,XX @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
63
return 0;
64
}
65
66
+/* nbd_read_eof
67
+ * Tries to read @size bytes from @ioc.
68
+ * Returns 1 on success
69
+ * 0 on eof, when no data was read (errp is not set)
70
+ * negative errno on failure (errp is set)
71
+ */
72
+static inline int coroutine_fn
73
+nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size, Error **errp)
74
+{
75
+ int ret;
76
+
77
+ assert(size);
78
+ ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
79
+ if (ret < 0) {
80
+ ret = -EIO;
81
+ }
82
+ return ret;
83
+}
84
+
85
/* nbd_receive_reply
86
* Returns 1 on success
87
* 0 on eof, when no data was read (errp is not set)
88
* negative errno on failure (errp is set)
89
*/
90
-int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
91
+int coroutine_fn nbd_receive_reply(QIOChannel *ioc, NBDReply *reply,
92
+ Error **errp)
93
{
94
int ret;
95
const char *type;
26
--
96
--
27
2.19.1
97
2.20.1
28
98
29
99
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open a read-write NBD
1
Instead of using the convenience wrapper qio_channel_read_all_eof(), use
2
connection if the server provides a read-write export, but instead of
2
the lower level QIOChannel API. This means duplicating some code, but
3
erroring out for read-only exports, just degrade to read-only.
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
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.
4
10
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
13
---
8
block/nbd-client.c | 10 +++++-----
14
include/block/nbd.h | 4 ++--
9
1 file changed, 5 insertions(+), 5 deletions(-)
15
block/nbd-client.c | 8 +-------
16
nbd/client.c | 46 ++++++++++++++++++++++++++++++++++++---------
17
3 files changed, 40 insertions(+), 18 deletions(-)
10
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);
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
34
diff --git a/block/nbd-client.c b/block/nbd-client.c
12
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
13
--- a/block/nbd-client.c
36
--- a/block/nbd-client.c
14
+++ b/block/nbd-client.c
37
+++ b/block/nbd-client.c
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
38
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_connection_entry(void *opaque)
16
logout("Failed to negotiate with the NBD server\n");
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) {
17
return ret;
125
return ret;
18
}
126
}
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
20
- !bdrv_is_read_only(bs)) {
21
- error_setg(errp,
22
- "request for write access conflicts with read-only export");
23
- return -EACCES;
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
26
+ if (ret < 0) {
27
+ return ret;
28
+ }
29
}
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
31
bs->supported_write_flags = BDRV_REQ_FUA;
32
--
127
--
33
2.19.1
128
2.20.1
34
129
35
130
diff view generated by jsdifflib
1
From: Leonid Bloch <lbloch@janustech.com>
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().
2
4
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
4
for the purpose of having convenient shortcuts for these sizes in cases
5
when the literal number has to be present at compile time, and
6
expressions as '(1 * KiB)' can not be used. One such case is the
7
stringification of sizes. Beyond that, it is convenient to use these
8
shortcuts for all power-of-two sizes, even if they don't have to be
9
literal numbers.
10
11
Despite its convenience, this table introduced 55 lines of "dumb" code,
12
the purpose and origin of which are obscure without reading the message
13
of the commit which introduced it. This patch fixes that by adding a
14
comment to the code itself with a brief explanation for the reasoning
15
behind this table. This comment includes the short AWK script that
16
generated the table, so that anyone who's interested could make sure
17
that the values in it are correct (otherwise these values look as if
18
they were typed manually).
19
20
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
6
---
23
include/qemu/units.h | 18 ++++++++++++++++++
7
block/nbd-client.c | 20 ++++++++++++++++++--
24
1 file changed, 18 insertions(+)
8
1 file changed, 18 insertions(+), 2 deletions(-)
25
9
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
10
diff --git a/block/nbd-client.c b/block/nbd-client.c
27
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
28
--- a/include/qemu/units.h
12
--- a/block/nbd-client.c
29
+++ b/include/qemu/units.h
13
+++ b/block/nbd-client.c
30
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void nbd_client_detach_aio_context(BlockDriverState *bs)
31
#define PiB (INT64_C(1) << 50)
15
qio_channel_detach_aio_context(QIO_CHANNEL(client->ioc));
32
#define EiB (INT64_C(1) << 60)
16
}
33
17
34
+/*
18
+static void nbd_client_attach_aio_context_bh(void *opaque)
35
+ * The following lookup table is intended to be used when a literal string of
19
+{
36
+ * the number of bytes is required (for example if it needs to be stringified).
20
+ BlockDriverState *bs = opaque;
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
21
+ NBDClientSession *client = nbd_get_client_session(bs);
38
+ * This table is generated using the AWK script below:
39
+ *
40
+ * BEGIN {
41
+ * suffix="KMGTPE";
42
+ * for(i=10; i<64; i++) {
43
+ * val=2**i;
44
+ * s=substr(suffix, int(i/10), 1);
45
+ * n=2**(i%10);
46
+ * pad=21-int(log(n)/log(10));
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
48
+ * }
49
+ * }
50
+ */
51
+
22
+
52
#define S_1KiB 1024
23
+ /* The node is still drained, so we know the coroutine has yielded in
53
#define S_2KiB 2048
24
+ * nbd_read_eof(), the only place where bs->in_flight can reach 0, or it is
54
#define S_4KiB 4096
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)
55
--
47
--
56
2.19.1
48
2.20.1
57
49
58
50
diff view generated by jsdifflib
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
1
The explicit aio_poll() call in bdrv_set_aio_context() was added in
2
add as little auto-detection as possible so that management tools are
2
commit c2b6428d388 as a workaround for bdrv_drain() failing to achieve
3
explicit about their needs, -drive is a convenience option for human
3
to actually quiesce everything (specifically the NBD client code to
4
users. Enabling auto-read-only=on by default there enables users to use
4
switch AioContext).
5
read-only images for read-only guest devices without having to specify
5
6
read-only=on explicitly. If they try to attach the image to a read-write
6
Now that the NBD client has been fixed to complete this operation during
7
device, they will still get an error message.
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.
8
11
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
11
---
14
---
12
blockdev.c | 1 +
15
block.c | 4 ----
13
1 file changed, 1 insertion(+)
16
1 file changed, 4 deletions(-)
14
17
15
diff --git a/blockdev.c b/blockdev.c
18
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/blockdev.c
20
--- a/block.c
18
+++ b/blockdev.c
21
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
22
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
23
bdrv_parent_drained_begin(bs, NULL, false);
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
24
bdrv_drain(bs); /* ensure there are no in-flight requests */
22
read_only ? "on" : "off");
25
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
26
- while (aio_poll(ctx, false)) {
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
27
- /* wait for all bottom halves to execute */
25
28
- }
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
29
-
30
bdrv_detach_aio_context(bs);
31
32
/* This function executes in the old AioContext so acquire the new one in
27
--
33
--
28
2.19.1
34
2.20.1
29
35
30
36
diff view generated by jsdifflib
1
To fully change the read-only state of a node, we must not only change
1
When a drained node changes its AioContext, we need to move its
2
bs->read_only, but also update bs->open_flags.
2
aio_disable_external() to the new context, too.
3
4
Without this fix, drain_end will try to reenable the new context, which
5
has never been disabled, so an assertion failure is triggered.
3
6
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
---
9
---
8
block.c | 7 +++++++
10
block.c | 7 +++++++
9
1 file changed, 7 insertions(+)
11
1 file changed, 7 insertions(+)
10
12
11
diff --git a/block.c b/block.c
13
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/block.c
15
--- a/block.c
14
+++ b/block.c
16
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ void bdrv_detach_aio_context(BlockDriverState *bs)
18
bdrv_detach_aio_context(child->bs);
16
}
19
}
17
20
18
bs->read_only = read_only;
21
+ if (bs->quiesce_counter) {
19
+
22
+ aio_enable_external(bs->aio_context);
20
+ if (read_only) {
23
+ }
21
+ bs->open_flags &= ~BDRV_O_RDWR;
24
bs->aio_context = NULL;
22
+ } else {
25
}
23
+ bs->open_flags |= BDRV_O_RDWR;
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);
24
+ }
33
+ }
25
+
34
+
26
return 0;
35
bs->aio_context = new_context;
27
}
36
28
37
QLIST_FOREACH(child, &bs->children, next) {
29
--
38
--
30
2.19.1
39
2.20.1
31
40
32
41
diff view generated by jsdifflib
New patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
4
tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++
5
1 file changed, 32 insertions(+)
1
6
7
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
8
index XXXXXXX..XXXXXXX 100644
9
--- a/tests/test-bdrv-drain.c
10
+++ b/tests/test-bdrv-drain.c
11
@@ -XXX,XX +XXX,XX @@ static void test_append_to_drained(void)
12
blk_unref(blk);
13
}
14
15
+static void test_set_aio_context(void)
16
+{
17
+ BlockDriverState *bs;
18
+ IOThread *a = iothread_new();
19
+ IOThread *b = iothread_new();
20
+ AioContext *ctx_a = iothread_get_aio_context(a);
21
+ AioContext *ctx_b = iothread_get_aio_context(b);
22
+
23
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
24
+ &error_abort);
25
+
26
+ bdrv_drained_begin(bs);
27
+ bdrv_set_aio_context(bs, ctx_a);
28
+
29
+ aio_context_acquire(ctx_a);
30
+ bdrv_drained_end(bs);
31
+
32
+ bdrv_drained_begin(bs);
33
+ bdrv_set_aio_context(bs, ctx_b);
34
+ aio_context_release(ctx_a);
35
+ aio_context_acquire(ctx_b);
36
+ bdrv_set_aio_context(bs, qemu_get_aio_context());
37
+ aio_context_release(ctx_b);
38
+ bdrv_drained_end(bs);
39
+
40
+ bdrv_unref(bs);
41
+ iothread_join(a);
42
+ iothread_join(b);
43
+}
44
+
45
int main(int argc, char **argv)
46
{
47
int ret;
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
49
50
g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained);
51
52
+ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context);
53
+
54
ret = g_test_run();
55
qemu_event_destroy(&done_event);
56
return ret;
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the file
1
Now that bdrv_set_aio_context() works inside drained sections, it can
2
read-write if we have the permissions, but instead of erroring out for
2
also use the real drain function instead of open coding something
3
read-only files, just degrade to read-only.
3
similar.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Niels de Vos <ndevos@redhat.com>
7
---
6
---
8
block/gluster.c | 12 ++++++++++--
7
block.c | 15 ++++++---------
9
1 file changed, 10 insertions(+), 2 deletions(-)
8
1 file changed, 6 insertions(+), 9 deletions(-)
10
9
11
diff --git a/block/gluster.c b/block/gluster.c
10
diff --git a/block.c b/block.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/block/gluster.c
12
--- a/block.c
14
+++ b/block/gluster.c
13
+++ b/block.c
15
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
14
@@ -XXX,XX +XXX,XX @@ void bdrv_attach_aio_context(BlockDriverState *bs,
16
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
15
bs->walking_aio_notifiers = false;
17
16
}
18
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
17
19
- if (!s->fd) {
18
+/* The caller must own the AioContext lock for the old AioContext of bs, but it
20
- ret = -errno;
19
+ * must not own the AioContext lock for new_context (unless new_context is
21
+ ret = s->fd ? 0 : -errno;
20
+ * the same as the current context of bs). */
22
+
21
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
23
+ if (ret == -EACCES || ret == -EROFS) {
22
{
24
+ /* Try to degrade to read-only, but if it doesn't work, still use the
23
- AioContext *ctx = bdrv_get_aio_context(bs);
25
+ * normal error message. */
24
-
26
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
25
- if (ctx == new_context) {
27
+ open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
26
+ if (bdrv_get_aio_context(bs) == new_context) {
28
+ s->fd = glfs_open(s->glfs, gconf->path, open_flags);
27
return;
29
+ ret = s->fd ? 0 : -errno;
30
+ }
31
}
28
}
32
29
33
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
30
- aio_disable_external(ctx);
31
- bdrv_parent_drained_begin(bs, NULL, false);
32
- bdrv_drain(bs); /* ensure there are no in-flight requests */
33
-
34
+ bdrv_drained_begin(bs);
35
bdrv_detach_aio_context(bs);
36
37
/* This function executes in the old AioContext so acquire the new one in
38
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
39
*/
40
aio_context_acquire(new_context);
41
bdrv_attach_aio_context(bs, new_context);
42
- bdrv_parent_drained_end(bs, NULL, false);
43
- aio_enable_external(ctx);
44
+ bdrv_drained_end(bs);
45
aio_context_release(new_context);
46
}
47
34
--
48
--
35
2.19.1
49
2.20.1
36
50
37
51
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, open the volume
1
aio_poll() has an existing assertion that the function is only called
2
read-write if we have the permissions, but instead of erroring out for
2
from the AioContext's home thread if blocking is allowed.
3
read-only volumes, just degrade to read-only.
3
4
This is not enough, some handlers make assumptions about the thread they
5
run in. Extend the assertion to non-blocking calls, too.
4
6
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
9
---
8
block/iscsi.c | 8 +++++---
10
util/aio-posix.c | 3 ++-
9
1 file changed, 5 insertions(+), 3 deletions(-)
11
1 file changed, 2 insertions(+), 1 deletion(-)
10
12
11
diff --git a/block/iscsi.c b/block/iscsi.c
13
diff --git a/util/aio-posix.c b/util/aio-posix.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/block/iscsi.c
15
--- a/util/aio-posix.c
14
+++ b/block/iscsi.c
16
+++ b/util/aio-posix.c
15
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
17
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
16
/* Check the write protect flag of the LUN if we want to write */
18
int64_t timeout;
17
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
19
int64_t start = 0;
18
iscsilun->write_protected) {
20
19
- error_setg(errp, "Cannot open a write protected LUN as read-write");
21
+ assert(in_aio_context_home_thread(ctx));
20
- ret = -EACCES;
22
+
21
- goto out;
23
/* aio_notify can avoid the expensive event_notifier_set if
22
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
24
* everything (file descriptors, bottom halves, timers) will
23
+ if (ret < 0) {
25
* be re-evaluated before the next blocking poll(). This is
24
+ goto out;
26
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
25
+ }
27
* so disable the optimization now.
26
+ flags &= ~BDRV_O_RDWR;
28
*/
29
if (blocking) {
30
- assert(in_aio_context_home_thread(ctx));
31
atomic_add(&ctx->notify_me, 2);
27
}
32
}
28
33
29
iscsi_readcapacity_sync(iscsilun, &local_err);
30
--
34
--
31
2.19.1
35
2.20.1
32
36
33
37
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
3
As it already said in the comment, we don't want to create loops in
4
parent->child relations. So, when we try to append @to to @c, we should
5
check that @c is not in @to children subtree, and we should check it
6
recursively, not only the first level. The patch provides BFS-based
7
search, to check the relations.
8
9
This is needed for further fleecing-hook filter usage: we need to
10
append it to source, when the hook is already a parent of target, and
11
source may be in a backing chain of target (fleecing-scheme). So, on
12
appending, the hook should not became a child (direct or through
13
children subtree) of the target.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
17
---
6
block.c | 6 +++---
18
block.c | 43 +++++++++++++++++++++++++++++++++++++------
7
1 file changed, 3 insertions(+), 3 deletions(-)
19
1 file changed, 37 insertions(+), 6 deletions(-)
8
20
9
diff --git a/block.c b/block.c
21
diff --git a/block.c b/block.c
10
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
11
--- a/block.c
23
--- a/block.c
12
+++ b/block.c
24
+++ b/block.c
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
25
@@ -XXX,XX +XXX,XX @@ void bdrv_close_all(void)
14
.help = "try to optimize zero writes (off, on, unmap)",
26
15
},
27
static bool should_update_child(BdrvChild *c, BlockDriverState *to)
16
{
28
{
17
- .name = "discard",
29
- BdrvChild *to_c;
18
+ .name = BDRV_OPT_DISCARD,
30
+ GQueue *queue;
19
.type = QEMU_OPT_STRING,
31
+ GHashTable *found;
20
.help = "discard operation (ignore/off, unmap/on)",
32
+ bool ret;
21
},
33
22
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
34
if (c->role->stay_at_node) {
35
return false;
36
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
37
* if A is a child of B, that means we cannot replace A by B there
38
* because that would create a loop. Silently detaching A from B
39
* is also not really an option. So overall just leaving A in
40
- * place there is the most sensible choice. */
41
- QLIST_FOREACH(to_c, &to->children, next) {
42
- if (to_c == c) {
43
- return false;
44
+ * place there is the most sensible choice.
45
+ *
46
+ * We would also create a loop in any cases where @c is only
47
+ * indirectly referenced by @to. Prevent this by returning false
48
+ * if @c is found (by breadth-first search) anywhere in the whole
49
+ * subtree of @to.
50
+ */
51
+
52
+ ret = true;
53
+ found = g_hash_table_new(NULL, NULL);
54
+ g_hash_table_add(found, to);
55
+ queue = g_queue_new();
56
+ g_queue_push_tail(queue, to);
57
+
58
+ while (!g_queue_is_empty(queue)) {
59
+ BlockDriverState *v = g_queue_pop_head(queue);
60
+ BdrvChild *c2;
61
+
62
+ QLIST_FOREACH(c2, &v->children, next) {
63
+ if (c2 == c) {
64
+ ret = false;
65
+ break;
66
+ }
67
+
68
+ if (g_hash_table_contains(found, c2->bs)) {
69
+ continue;
70
+ }
71
+
72
+ g_queue_push_tail(queue, c2->bs);
73
+ g_hash_table_add(found, c2->bs);
23
}
74
}
24
}
75
}
25
76
26
- discard = qemu_opt_get(opts, "discard");
77
- return true;
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
78
+ g_queue_free(queue);
28
if (discard != NULL) {
79
+ g_hash_table_destroy(found);
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
80
+
30
error_setg(errp, "Invalid discard option");
81
+ return ret;
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
82
}
32
83
33
update_flags_from_options(&reopen_state->flags, opts);
84
void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
34
35
- discard = qemu_opt_get_del(opts, "discard");
36
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
37
if (discard != NULL) {
38
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
39
error_setg(errp, "Invalid discard option");
40
--
85
--
41
2.19.1
86
2.20.1
42
87
43
88
diff view generated by jsdifflib
1
From: Cleber Rosa <crosa@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
While testing the Python 3 changes which touch the 083 test, I noticed
3
bdrv_check_perm in it's recursion checks each node in context of new
4
that it would fail with qcow2. Expanding the testing, I noticed it
4
permissions for one parent, because of nature of DFS. It works well,
5
had nothing to do with the Python 3 changes, and in fact, it would not
5
while children subgraph of top-most updated node is a tree, i.e. it
6
pass on anything but raw:
6
doesn't have any kind of loops. But if we have a loop (not oriented,
7
of course), i.e. we have two different ways from top-node to some
8
child-node, then bdrv_check_perm will do wrong thing:
7
9
8
raw: pass
10
top
9
bochs: not generic
11
| \
10
cloop: not generic
12
| |
11
parallels: fail
13
v v
12
qcow: fail
14
A B
13
qcow2: fail
15
| |
14
qed: fail
16
v v
15
vdi: fail
17
node
16
vhdx: fail
17
vmdk: fail
18
vpc: fail
19
luks: fail
20
18
21
The errors are a mixture I/O and "image not in xxx format", such as:
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.
22
24
23
=== Check disconnect before data ===
25
The following commit will add a test, which shows this bug.
24
26
25
Unexpected end-of-file before all bytes were read
27
To fix this situation, let's really set BdrvChild permissions during
26
-read failed: Input/output error
28
bdrv_check_perm procedure. And we are happy here, as check-perm is
27
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Could not open 'nbd://127.0.0.1:PORT/foo': Input/output error
29
already written in transaction manner, so we just need to restore
30
backed-up permissions in _abort.
28
31
29
=== Check disconnect after data ===
32
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
30
31
-read 512/512 bytes at offset 0
32
-512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
33
+can't open device nbd+tcp://127.0.0.1:PORT/foo: Image not in qcow format
34
35
I'm not aware if there's a quick fix, so, for the time being, it looks
36
like the honest approach is to make the test known to work on raw
37
only.
38
39
Signed-off-by: Cleber Rosa <crosa@redhat.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
33
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
41
---
34
---
42
tests/qemu-iotests/083 | 2 +-
35
include/block/block_int.h | 5 +++++
43
1 file changed, 1 insertion(+), 1 deletion(-)
36
block.c | 27 ++++++++++++++++++++++++++-
37
2 files changed, 31 insertions(+), 1 deletion(-)
44
38
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
39
diff --git a/include/block/block_int.h b/include/block/block_int.h
46
index XXXXXXX..XXXXXXX 100755
40
index XXXXXXX..XXXXXXX 100644
47
--- a/tests/qemu-iotests/083
41
--- a/include/block/block_int.h
48
+++ b/tests/qemu-iotests/083
42
+++ b/include/block/block_int.h
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
43
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
50
. ./common.rc
44
*/
51
. ./common.filter
45
uint64_t shared_perm;
52
46
53
-_supported_fmt generic
47
+ /* backup of permissions during permission update procedure */
54
+_supported_fmt raw
48
+ bool has_backup_perm;
55
_supported_proto nbd
49
+ uint64_t backup_perm;
56
_supported_os Linux
50
+ uint64_t backup_shared_perm;
51
+
52
QLIST_ENTRY(BdrvChild) next;
53
QLIST_ENTRY(BdrvChild) next_parent;
54
};
55
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
58
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q,
60
ret = bdrv_check_update_perm(c->bs, q, perm, shared, ignore_children, errp);
61
g_slist_free(ignore_children);
62
63
- return ret;
64
+ if (ret < 0) {
65
+ return ret;
66
+ }
67
+
68
+ if (!c->has_backup_perm) {
69
+ c->has_backup_perm = true;
70
+ c->backup_perm = c->perm;
71
+ c->backup_shared_perm = c->shared_perm;
72
+ }
73
+ /*
74
+ * Note: it's OK if c->has_backup_perm was already set, as we can find the
75
+ * same child twice during check_perm procedure
76
+ */
77
+
78
+ c->perm = perm;
79
+ c->shared_perm = shared;
80
+
81
+ return 0;
82
}
83
84
static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
85
{
86
uint64_t cumulative_perms, cumulative_shared_perms;
87
88
+ c->has_backup_perm = false;
89
+
90
c->perm = perm;
91
c->shared_perm = shared;
92
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared)
94
95
static void bdrv_child_abort_perm_update(BdrvChild *c)
96
{
97
+ if (c->has_backup_perm) {
98
+ c->perm = c->backup_perm;
99
+ c->shared_perm = c->backup_shared_perm;
100
+ c->has_backup_perm = false;
101
+ }
102
+
103
bdrv_abort_perm_update(c->bs);
104
}
57
105
58
--
106
--
59
2.19.1
107
2.20.1
60
108
61
109
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
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
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This doesn't have any practical effect at the moment because the
3
L1 table entries have a field to store the offset of an L2 table.
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
4
The rest of the bits of the entry are currently reserved except from
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
5
bit 63, which stores the COPIED flag.
6
future encryption methods could have different requirements.
6
7
The offset is always taken from the entry using L1E_OFFSET_MASK to
8
ensure that we only use the bits that belong to that field.
9
10
While that mask is used every time we read from the L1 table, it is
11
never used when we write to it. Due to the limits set elsewhere in the
12
code QEMU can never produce L2 table offsets that don't fit in that
13
field so any such offset when allocating an L2 table would indicate a
14
bug in QEMU.
7
15
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
19
---
12
block/qcow2.c | 2 +-
20
block/qcow2-cluster.c | 3 +++
13
1 file changed, 1 insertion(+), 1 deletion(-)
21
1 file changed, 3 insertions(+)
14
22
15
diff --git a/block/qcow2.c b/block/qcow2.c
23
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
25
--- a/block/qcow2-cluster.c
18
+++ b/block/qcow2.c
26
+++ b/block/qcow2-cluster.c
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
27
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
20
28
goto fail;
21
if (bs->encrypted) {
22
/* Encryption works on a sector granularity */
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
25
}
29
}
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
30
27
bs->bl.pdiscard_alignment = s->cluster_size;
31
+ /* The offset must fit in the offset field of the L1 table entry */
32
+ assert((l2_offset & L1E_OFFSET_MASK) == l2_offset);
33
+
34
/* If we're allocating the table at offset 0 then something is wrong */
35
if (l2_offset == 0) {
36
qcow2_signal_corruption(bs, true, -1, -1, "Preventing invalid "
28
--
37
--
29
2.19.1
38
2.20.1
30
39
31
40
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
When using the vvfat driver with a directory that contains too many files,
3
The QEMU_PACKED is causing a compiler warning/error with GCC 9:
4
QEMU currently crashes. This can be triggered like this for example:
5
4
6
mkdir /tmp/vvfattest
5
CC block/nvme.o
7
cd /tmp/vvfattest
6
block/nvme.c: In function ‘nvme_create_queue_pair’:
8
for ((x=0;x<=513;x++)); do mkdir $x; done
7
block/nvme.c:209:22: error: taking address of packed member of
9
qemu-system-x86_64 -drive \
8
‘struct <anonymous>’ may result in an unaligned pointer value
10
file.driver=vvfat,file.dir=.,read-only=on,media=cdrom
9
[-Werror=address-of-packed-member]
10
209 | q->sq.doorbell = &s->regs->doorbells[idx * 2 * s->doorbell_scale];
11
11
12
Seems like read_directory() is changing the mapping->path variable. Make
12
All members of the struct are naturally aligned, so there should
13
sure we use the right pointer instead.
13
not be the need for QEMU_PACKED here, and the following QEMU_BUILD_BUG_ON
14
also ensures that there is no padding. Thus simply remove the QEMU_PACKED
15
here.
14
16
17
Buglink: https://bugs.launchpad.net/qemu/+bug/1817525
18
Reported-by: Satheesh Rajendran <sathnaga@linux.vnet.ibm.com>
15
Signed-off-by: Thomas Huth <thuth@redhat.com>
19
Signed-off-by: Thomas Huth <thuth@redhat.com>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
22
---
18
block/vvfat.c | 4 ++--
23
block/nvme.c | 2 +-
19
1 file changed, 2 insertions(+), 2 deletions(-)
24
1 file changed, 1 insertion(+), 1 deletion(-)
20
25
21
diff --git a/block/vvfat.c b/block/vvfat.c
26
diff --git a/block/nvme.c b/block/nvme.c
22
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
23
--- a/block/vvfat.c
28
--- a/block/nvme.c
24
+++ b/block/vvfat.c
29
+++ b/block/nvme.c
25
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
30
@@ -XXX,XX +XXX,XX @@ typedef volatile struct {
26
mapping = array_get(&(s->mapping), i);
31
uint8_t reserved1[0xec0];
27
32
uint8_t cmd_set_specfic[0x100];
28
if (mapping->mode & MODE_DIRECTORY) {
33
uint32_t doorbells[];
29
+ char *path = mapping->path;
34
-} QEMU_PACKED NVMeRegs;
30
mapping->begin = cluster;
35
+} NVMeRegs;
31
if(read_directory(s, i)) {
36
32
- error_setg(errp, "Could not read directory %s",
37
QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
33
- mapping->path);
38
34
+ error_setg(errp, "Could not read directory %s", path);
35
return -1;
36
}
37
mapping = array_get(&(s->mapping), i);
38
--
39
--
39
2.19.1
40
2.20.1
40
41
41
42
diff view generated by jsdifflib
New patch
1
1
From: Max Reitz <mreitz@redhat.com>
2
3
Before this patch, bdrv_refresh_filename() is used in a pushing manner:
4
Whenever the BDS graph is modified, the parents of the modified edges
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
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
Message-id: 20190201192935.18394-2-mreitz@redhat.com
27
Reviewed-by: Eric Blake <eblake@redhat.com>
28
Signed-off-by: Max Reitz <mreitz@redhat.com>
29
---
30
include/block/block.h | 1 -
31
block.c | 31 +++++++++++++++----------------
32
block/qapi.c | 4 ++++
33
block/raw-format.c | 1 +
34
block/replication.c | 2 --
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
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
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
56
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
58
void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
59
Error **errp)
60
{
61
- char *backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
62
+ char *backed;
63
64
+ bdrv_refresh_filename(bs);
65
+
66
+ backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
67
bdrv_get_full_backing_filename_from_filename(backed, bs->backing_file,
68
dest, sz, errp);
69
}
70
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_attach(BdrvChild *c)
71
"node is used as backing hd of '%s'",
72
bdrv_get_device_or_node_name(parent));
73
74
+ bdrv_refresh_filename(backing_hd);
75
+
76
parent->open_flags &= ~BDRV_O_NO_BACKING;
77
pstrcpy(parent->backing_file, sizeof(parent->backing_file),
78
backing_hd->filename);
79
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
80
}
81
82
if (file != NULL) {
83
+ bdrv_refresh_filename(blk_bs(file));
84
filename = blk_bs(file)->filename;
85
} else {
86
/*
87
@@ -XXX,XX +XXX,XX @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
88
bdrv_unref(backing_hd);
89
}
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
175
index XXXXXXX..XXXXXXX 100644
176
--- a/block/raw-format.c
177
+++ b/block/raw-format.c
178
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
179
bs->file->bs->supported_zero_flags);
180
181
if (bs->probed && !bdrv_is_read_only(bs)) {
182
+ bdrv_refresh_filename(bs->file->bs);
183
fprintf(stderr,
184
"WARNING: Image format was not specified for '%s' and probing "
185
"guessed raw.\n"
186
diff --git a/block/replication.c b/block/replication.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/block/replication.c
189
+++ b/block/replication.c
190
@@ -XXX,XX +XXX,XX @@ static void replication_done(void *opaque, int ret)
191
if (ret == 0) {
192
s->stage = BLOCK_REPLICATION_DONE;
193
194
- /* refresh top bs's filename */
195
- bdrv_refresh_filename(bs);
196
s->active_disk = NULL;
197
s->secondary_disk = NULL;
198
s->hidden_disk = NULL;
199
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
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
}
282
283
@@ -XXX,XX +XXX,XX @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
284
goto out;
285
}
286
} else if (has_top && top) {
287
+ /* This strcmp() is just a shortcut, there is no need to
288
+ * refresh @bs's filename. If it mismatches,
289
+ * bdrv_find_backing_image() will do the refresh and may still
290
+ * return @bs. */
291
if (strcmp(bs->filename, top) != 0) {
292
top_bs = bdrv_find_backing_image(bs, top);
293
}
294
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
295
if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
296
assert(backup->format);
297
if (source) {
298
+ bdrv_refresh_filename(source);
299
bdrv_img_create(backup->target, backup->format, source->filename,
300
source->drv->format_name, NULL,
301
size, flags, false, &local_err);
302
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
303
break;
304
case NEW_IMAGE_MODE_ABSOLUTE_PATHS:
305
/* create new image with backing file */
306
+ bdrv_refresh_filename(source);
307
bdrv_img_create(arg->target, format,
308
source->filename,
309
source->drv->format_name,
310
diff --git a/qemu-img.c b/qemu-img.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/qemu-img.c
313
+++ b/qemu-img.c
314
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
315
BlockDriverState *file;
316
bool has_offset;
317
int64_t map;
318
+ char *filename = NULL;
319
320
/* As an optimization, we could cache the current range of unallocated
321
* clusters in each file of the chain, and avoid querying the same
322
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
323
324
has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);
325
326
+ if (file && has_offset) {
327
+ bdrv_refresh_filename(file);
328
+ filename = file->filename;
329
+ }
330
+
331
*e = (MapEntry) {
332
.start = offset,
333
.length = bytes,
334
@@ -XXX,XX +XXX,XX @@ static int get_block_status(BlockDriverState *bs, int64_t offset,
335
.offset = map,
336
.has_offset = has_offset,
337
.depth = depth,
338
- .has_filename = file && has_offset,
339
- .filename = file && has_offset ? file->filename : NULL,
340
+ .has_filename = filename,
341
+ .filename = filename,
342
};
343
344
return 0;
345
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
346
qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
347
}
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
--
354
2.20.1
355
356
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Just like in qemu_opts_print_help(), print the device name as a caption
3
bdrv_refresh_filename() should invoke itself recursively on all
4
instead of on every single line, indent all options, add angle brackets
4
children, not just on file.
5
around types, and align the descriptions after 24 characters. Also,
5
6
separate the descriptions with " - " instead of putting them in
6
With that change, we can remove the manual invocations in blkverify,
7
parentheses, because that is what we do everywhere else. This does look
7
quorum, commit, mirror, and blklogwrites.
8
a bit funny here because basically all bits have the description
9
"on/off", but funny does not mean it is less readable.
10
8
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20190201192935.18394-3-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
14
---
15
qdev-monitor.c | 13 +++++++++++--
15
block.c | 9 +++++----
16
1 file changed, 11 insertions(+), 2 deletions(-)
16
block/blklogwrites.c | 3 ---
17
block/blkverify.c | 3 ---
18
block/commit.c | 1 -
19
block/mirror.c | 1 -
20
block/quorum.c | 1 -
21
6 files changed, 5 insertions(+), 13 deletions(-)
17
22
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
23
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/qdev-monitor.c
25
--- a/block.c
21
+++ b/qdev-monitor.c
26
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
27
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
23
goto error;
28
void bdrv_refresh_filename(BlockDriverState *bs)
29
{
30
BlockDriver *drv = bs->drv;
31
+ BdrvChild *child;
32
QDict *opts;
33
34
if (!drv) {
35
return;
24
}
36
}
25
37
26
+ if (prop_list) {
38
- /* This BDS's file name will most probably depend on its file's name, so
27
+ out_printf("%s options:\n", driver);
39
- * refresh that first */
28
+ } else {
40
- if (bs->file) {
29
+ out_printf("There are no options for %s.\n", driver);
41
- bdrv_refresh_filename(bs->file->bs);
30
+ }
42
+ /* This BDS's file name may depend on any of its children's file names, so
31
for (prop = prop_list; prop; prop = prop->next) {
43
+ * refresh those first */
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
44
+ QLIST_FOREACH(child, &bs->children, next) {
33
+ int len;
45
+ bdrv_refresh_filename(child->bs);
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
46
}
35
if (prop->value->has_description) {
47
36
- out_printf(" (%s)\n", prop->value->description);
48
if (drv->bdrv_refresh_filename) {
37
+ if (len < 24) {
49
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
38
+ out_printf("%*s", 24 - len, "");
50
index XXXXXXX..XXXXXXX 100644
39
+ }
51
--- a/block/blklogwrites.c
40
+ out_printf(" - %s\n", prop->value->description);
52
+++ b/block/blklogwrites.c
41
} else {
53
@@ -XXX,XX +XXX,XX @@ static void blk_log_writes_refresh_filename(BlockDriverState *bs,
42
out_printf("\n");
54
{
55
BDRVBlkLogWritesState *s = bs->opaque;
56
57
- /* bs->file->bs has already been refreshed */
58
- bdrv_refresh_filename(s->log_file->bs);
59
-
60
if (bs->file->bs->full_open_options
61
&& s->log_file->bs->full_open_options)
62
{
63
diff --git a/block/blkverify.c b/block/blkverify.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/block/blkverify.c
66
+++ b/block/blkverify.c
67
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
68
{
69
BDRVBlkverifyState *s = bs->opaque;
70
71
- /* bs->file->bs has already been refreshed */
72
- bdrv_refresh_filename(s->test_file->bs);
73
-
74
if (bs->file->bs->full_open_options
75
&& s->test_file->bs->full_open_options)
76
{
77
diff --git a/block/commit.c b/block/commit.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/commit.c
80
+++ b/block/commit.c
81
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
82
83
static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
84
{
85
- bdrv_refresh_filename(bs->backing->bs);
86
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
87
bs->backing->bs->filename);
88
}
89
diff --git a/block/mirror.c b/block/mirror.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/block/mirror.c
92
+++ b/block/mirror.c
93
@@ -XXX,XX +XXX,XX @@ static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
94
* bdrv_set_backing_hd */
95
return;
96
}
97
- bdrv_refresh_filename(bs->backing->bs);
98
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
99
bs->backing->bs->filename);
100
}
101
diff --git a/block/quorum.c b/block/quorum.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/block/quorum.c
104
+++ b/block/quorum.c
105
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
106
int i;
107
108
for (i = 0; i < s->num_children; i++) {
109
- bdrv_refresh_filename(s->children[i]->bs);
110
if (!s->children[i]->bs->full_open_options) {
111
return;
43
}
112
}
44
--
113
--
45
2.19.1
114
2.20.1
46
115
47
116
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
bdrv_refresh_filename() should simply skip all implicit nodes. They are
4
supposed to be invisible to the user, so they should not appear in
5
filename information.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-4-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block.c | 14 ++++++++++++++
14
1 file changed, 14 insertions(+)
15
16
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
21
bdrv_refresh_filename(child->bs);
22
}
23
24
+ if (bs->implicit) {
25
+ /* For implicit nodes, just copy everything from the single child */
26
+ child = QLIST_FIRST(&bs->children);
27
+ assert(QLIST_NEXT(child, next) == NULL);
28
+
29
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
30
+ child->bs->exact_filename);
31
+ pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
32
+
33
+ bs->full_open_options = qobject_ref(child->bs->full_open_options);
34
+
35
+ return;
36
+ }
37
+
38
if (drv->bdrv_refresh_filename) {
39
/* Obsolete information is of no use here, so drop the old file name
40
* information before refreshing it */
41
--
42
2.20.1
43
44
diff view generated by jsdifflib
New patch
1
1
From: Max Reitz <mreitz@redhat.com>
2
3
If the backing file is overridden, this most probably does change the
4
guest-visible data of a BDS. Therefore, we will need to consider this
5
in bdrv_refresh_filename().
6
7
To see whether it has been overridden, we might want to compare
8
bs->backing_file and bs->backing->bs->filename. However,
9
bs->backing_file is changed by bdrv_set_backing_hd() (which is just used
10
to change the backing child at runtime, without modifying the image
11
header), so bs->backing_file most of the time simply contains a copy of
12
bs->backing->bs->filename anyway, so it is useless for such a
13
comparison.
14
15
This patch adds an auto_backing_file BDS field which contains the
16
backing file path as indicated by the image header, which is not changed
17
by bdrv_set_backing_hd().
18
19
Because of bdrv_refresh_filename() magic, however, a BDS's filename may
20
differ from what has been specified during bdrv_open(). Then, the
21
comparison between bs->auto_backing_file and bs->backing->bs->filename
22
may fail even though bs->backing was opened from bs->auto_backing_file.
23
To mitigate this, we can copy the real BDS's filename (after the whole
24
bdrv_open() and bdrv_refresh_filename() process) into
25
bs->auto_backing_file, if we know the former has been opened based on
26
the latter. This is only possible if no options modifying the backing
27
file's behavior have been specified, though. To simplify things, this
28
patch only copies the filename from the backing file if no options have
29
been specified for it at all.
30
31
Furthermore, there are cases where an overlay is created by qemu which
32
already contains a BDS's filename (e.g. in blockdev-snapshot-sync). We
33
do not need to worry about updating the overlay's bs->auto_backing_file
34
there, because we actually wrote a post-bdrv_refresh_filename() filename
35
into the image header.
36
37
So all in all, there will be false negatives where (as of a future
38
patch) bdrv_refresh_filename() will assume that the backing file differs
39
from what was specified in the image header, even though it really does
40
not. However, these cases should be limited to where (1) the user
41
actually did override something in the backing chain (e.g. by specifying
42
options for the backing file), or (2) the user executed a QMP command to
43
change some node's backing file (e.g. change-backing-file or
44
block-commit with @backing-file given) where the given filename does not
45
happen to coincide with qemu's idea of the backing BDS's filename.
46
47
Then again, (1) really is limited to -drive. With -blockdev or
48
blockdev-add, you have to adhere to the schema, so a user cannot give
49
partial "unimportant" options (e.g. by just setting backing.node-name
50
and leaving the rest to the image header). Therefore, trying to fix
51
this would mean trying to fix something for -drive only.
52
53
To improve on (2), we would need a full infrastructure to "canonicalize"
54
an arbitrary filename (+ options), so it can be compared against
55
another. That seems a bit over the top, considering that filenames
56
nowadays are there mostly for the user's entertainment.
57
58
Signed-off-by: Max Reitz <mreitz@redhat.com>
59
Reviewed-by: Eric Blake <eblake@redhat.com>
60
Reviewed-by: Alberto Garcia <berto@igalia.com>
61
Message-id: 20190201192935.18394-5-mreitz@redhat.com
62
Signed-off-by: Max Reitz <mreitz@redhat.com>
63
---
64
include/block/block_int.h | 4 ++++
65
block.c | 19 +++++++++++++++++++
66
block/qcow.c | 7 +++++--
67
block/qcow2.c | 10 +++++++---
68
block/qed.c | 7 +++++--
69
block/vmdk.c | 6 ++++--
70
6 files changed, 44 insertions(+), 9 deletions(-)
71
72
diff --git a/include/block/block_int.h b/include/block/block_int.h
73
index XXXXXXX..XXXXXXX 100644
74
--- a/include/block/block_int.h
75
+++ b/include/block/block_int.h
76
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
77
char filename[PATH_MAX];
78
char backing_file[PATH_MAX]; /* if non zero, the image is a diff of
79
this file image */
80
+ /* The backing filename indicated by the image header; if we ever
81
+ * open this file, then this is replaced by the resulting BDS's
82
+ * filename (i.e. after a bdrv_refresh_filename() run). */
83
+ char auto_backing_file[PATH_MAX];
84
char backing_format[16]; /* if non-zero and backing_file exists */
85
86
QDict *full_open_options;
87
diff --git a/block.c b/block.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block.c
90
+++ b/block.c
91
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
92
char *bdref_key_dot;
93
const char *reference = NULL;
94
int ret = 0;
95
+ bool implicit_backing = false;
96
BlockDriverState *backing_hd;
97
QDict *options;
98
QDict *tmp_parent_options = NULL;
99
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
100
qobject_unref(options);
101
goto free_exit;
102
} else {
103
+ if (qdict_size(options) == 0) {
104
+ /* If the user specifies options that do not modify the
105
+ * backing file's behavior, we might still consider it the
106
+ * implicit backing file. But it's easier this way, and
107
+ * just specifying some of the backing BDS's options is
108
+ * only possible with -drive anyway (otherwise the QAPI
109
+ * schema forces the user to specify everything). */
110
+ implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
111
+ }
112
+
113
bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
114
&local_err);
115
if (local_err) {
116
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
117
}
118
bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
119
120
+ if (implicit_backing) {
121
+ bdrv_refresh_filename(backing_hd);
122
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
123
+ backing_hd->filename);
124
+ }
125
+
126
/* Hook up the backing file link; drop our reference, bs owns the
127
* backing_hd reference now */
128
bdrv_set_backing_hd(bs, backing_hd, &local_err);
129
@@ -XXX,XX +XXX,XX @@ int bdrv_change_backing_file(BlockDriverState *bs,
130
if (ret == 0) {
131
pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: "");
132
pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: "");
133
+ pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file),
134
+ backing_file ?: "");
135
}
136
return ret;
137
}
138
diff --git a/block/qcow.c b/block/qcow.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/qcow.c
141
+++ b/block/qcow.c
142
@@ -XXX,XX +XXX,XX @@
143
#include "qemu/module.h"
144
#include "qemu/option.h"
145
#include "qemu/bswap.h"
146
+#include "qemu/cutils.h"
147
#include <zlib.h>
148
#include "qapi/qmp/qdict.h"
149
#include "qapi/qmp/qstring.h"
150
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
151
goto fail;
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
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
171
goto fail;
172
}
173
ret = bdrv_pread(bs->file, header.backing_file_offset,
174
- bs->backing_file, len);
175
+ bs->auto_backing_file, len);
176
if (ret < 0) {
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
198
diff --git a/block/qed.c b/block/qed.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/qed.c
201
+++ b/block/qed.c
202
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
203
}
204
205
ret = qed_read_string(bs->file, s->header.backing_filename_offset,
206
- s->header.backing_filename_size, bs->backing_file,
207
- sizeof(bs->backing_file));
208
+ s->header.backing_filename_size,
209
+ bs->auto_backing_file,
210
+ sizeof(bs->auto_backing_file));
211
if (ret < 0) {
212
return ret;
213
}
214
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
215
+ bs->auto_backing_file);
216
217
if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) {
218
pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw");
219
diff --git a/block/vmdk.c b/block/vmdk.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/block/vmdk.c
222
+++ b/block/vmdk.c
223
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
224
ret = -EINVAL;
225
goto out;
226
}
227
- if ((end_name - p_name) > sizeof(bs->backing_file) - 1) {
228
+ if ((end_name - p_name) > sizeof(bs->auto_backing_file) - 1) {
229
ret = -EINVAL;
230
goto out;
231
}
232
233
- pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
234
+ pstrcpy(bs->auto_backing_file, end_name - p_name + 1, p_name);
235
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
236
+ bs->auto_backing_file);
237
}
238
239
out:
240
--
241
2.20.1
242
243
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Basically, bdrv_refresh_filename() should respect all children of a
4
BlockDriverState. However, generally those children are driver-specific,
5
so this function cannot handle the general case. On the other hand,
6
there are only few drivers which use other children than @file and
7
@backing (that being vmdk, quorum, and blkverify).
8
9
Most block drivers only use @file and/or @backing (if they use any
10
children at all). Both can be implemented directly in
11
bdrv_refresh_filename.
12
13
The user overriding the file's filename is already handled, however, the
14
user overriding the backing file is not. If this is done, opening the
15
BDS with the plain filename of its file will not be correct, so we may
16
not set bs->exact_filename in that case.
17
18
iotest 051 contains test cases for overriding the backing file, and so
19
its output changes with this patch applied.
20
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
23
Message-id: 20190201192935.18394-6-mreitz@redhat.com
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
block.c | 38 ++++++++++++++++++++++++++++++++++-
27
tests/qemu-iotests/051.out | 8 ++++----
28
tests/qemu-iotests/051.pc.out | 8 ++++----
29
3 files changed, 45 insertions(+), 9 deletions(-)
30
31
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
34
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
36
return found_any;
37
}
38
39
+/* Note: This function may return false positives; it may return true
40
+ * even if opening the backing file specified by bs's image header
41
+ * would result in exactly bs->backing. */
42
+static bool bdrv_backing_overridden(BlockDriverState *bs)
43
+{
44
+ if (bs->backing) {
45
+ return strcmp(bs->auto_backing_file,
46
+ bs->backing->bs->filename);
47
+ } else {
48
+ /* No backing BDS, so if the image header reports any backing
49
+ * file, it must have been suppressed */
50
+ return bs->auto_backing_file[0] != '\0';
51
+ }
52
+}
53
+
54
/* Updates the following BDS fields:
55
* - exact_filename: A filename which may be used for opening a block device
56
* which (mostly) equals the given BDS (even without any
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
58
BlockDriver *drv = bs->drv;
59
BdrvChild *child;
60
QDict *opts;
61
+ bool backing_overridden;
62
63
if (!drv) {
64
return;
65
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
66
return;
67
}
68
69
+ backing_overridden = bdrv_backing_overridden(bs);
70
+
71
+ if (bs->open_flags & BDRV_O_NO_IO) {
72
+ /* Without I/O, the backing file does not change anything.
73
+ * Therefore, in such a case (primarily qemu-img), we can
74
+ * pretend the backing file has not been overridden even if
75
+ * it technically has been. */
76
+ backing_overridden = false;
77
+ }
78
+
79
if (drv->bdrv_refresh_filename) {
80
/* Obsolete information is of no use here, so drop the old file name
81
* information before refreshing it */
82
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
83
84
opts = qdict_new();
85
has_open_options = append_open_options(opts, bs);
86
+ has_open_options |= backing_overridden;
87
88
/* If no specific options have been given for this BDS, the filename of
89
* the underlying file should suffice for this one as well */
90
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
91
* file BDS. The full options QDict of that file BDS should somehow
92
* contain a representation of the filename, therefore the following
93
* suffices without querying the (exact_)filename of this BDS. */
94
- if (bs->file->bs->full_open_options) {
95
+ if (bs->file->bs->full_open_options &&
96
+ (!bs->backing || bs->backing->bs->full_open_options))
97
+ {
98
qdict_put_str(opts, "driver", drv->format_name);
99
qdict_put(opts, "file",
100
qobject_ref(bs->file->bs->full_open_options));
101
102
+ if (bs->backing) {
103
+ qdict_put(opts, "backing",
104
+ qobject_ref(bs->backing->bs->full_open_options));
105
+ } else if (backing_overridden) {
106
+ qdict_put_null(opts, "backing");
107
+ }
108
+
109
bs->full_open_options = opts;
110
} else {
111
qobject_unref(opts);
112
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
113
index XXXXXXX..XXXXXXX 100644
114
--- a/tests/qemu-iotests/051.out
115
+++ b/tests/qemu-iotests/051.out
116
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
117
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
118
QEMU X.Y.Z monitor - type 'help' for more information
119
(qemu) info block
120
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
121
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
122
Removable device: not locked, tray closed
123
Cache mode: writeback
124
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
125
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
126
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
127
QEMU X.Y.Z monitor - type 'help' for more information
128
(qemu) info block
129
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
130
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
131
Removable device: not locked, tray closed
132
Cache mode: writeback
133
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
134
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
135
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
136
QEMU X.Y.Z monitor - type 'help' for more information
137
(qemu) info block
138
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
139
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
140
Removable device: not locked, tray closed
141
Cache mode: writethrough
142
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
143
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
144
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
145
QEMU X.Y.Z monitor - type 'help' for more information
146
(qemu) info block
147
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
148
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
149
Removable device: not locked, tray closed
150
Cache mode: writeback, ignore flushes
151
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
152
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
153
index XXXXXXX..XXXXXXX 100644
154
--- a/tests/qemu-iotests/051.pc.out
155
+++ b/tests/qemu-iotests/051.pc.out
156
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
157
Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
158
QEMU X.Y.Z monitor - type 'help' for more information
159
(qemu) info block
160
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
161
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.orig"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
162
Removable device: not locked, tray closed
163
Cache mode: writeback
164
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
165
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
166
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
167
QEMU X.Y.Z monitor - type 'help' for more information
168
(qemu) info block
169
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
170
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
171
Removable device: not locked, tray closed
172
Cache mode: writeback
173
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
174
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
175
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
176
QEMU X.Y.Z monitor - type 'help' for more information
177
(qemu) info block
178
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
179
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
180
Removable device: not locked, tray closed
181
Cache mode: writethrough
182
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
183
@@ -XXX,XX +XXX,XX @@ backing-file: TEST_DIR/t.qcow2.base (file, read-only)
184
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
185
QEMU X.Y.Z monitor - type 'help' for more information
186
(qemu) info block
187
-drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
188
+drive0 (NODE_NAME): json:{"backing": {"driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}} (qcow2)
189
Removable device: not locked, tray closed
190
Cache mode: writeback, ignore flushes
191
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
192
--
193
2.20.1
194
195
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-7-mreitz@redhat.com
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/iotests.py | 10 ++++++++++
9
1 file changed, 10 insertions(+)
10
11
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/iotests.py
14
+++ b/tests/qemu-iotests/iotests.py
15
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
16
lines.append(line)
17
return '\n'.join(lines)
18
19
+def filter_imgfmt(msg):
20
+ return msg.replace(imgfmt, 'IMGFMT')
21
+
22
+def filter_qmp_imgfmt(qmsg):
23
+ def _filter(key, value):
24
+ if is_str(value):
25
+ return filter_imgfmt(value)
26
+ return value
27
+ return filter_qmp(qmsg, _filter)
28
+
29
def log(msg, filters=[], indent=None):
30
'''Logs either a string message or a JSON serializable message (like QMP).
31
If indent is provided, JSON serializable messages are pretty-printed.'''
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
This function queries a node; since we cannot do that right now, it
4
executes query-named-block-nodes and returns the matching node's object.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-id: 20190201192935.18394-8-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 7 +++++++
14
1 file changed, 7 insertions(+)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
21
else:
22
iotests.log(ev)
23
24
+ def node_info(self, node_name):
25
+ nodes = self.qmp('query-named-block-nodes')
26
+ for x in nodes['return']:
27
+ if x['node-name'] == node_name:
28
+ return x
29
+ return None
30
+
31
32
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-9-mreitz@redhat.com
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
---
6
---
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
7
tests/qemu-iotests/228 | 242 +++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
8
tests/qemu-iotests/228.out | 84 +++++++++++++
6
tests/qemu-iotests/group | 1 +
9
tests/qemu-iotests/group | 1 +
7
3 files changed, 207 insertions(+)
10
3 files changed, 327 insertions(+)
8
create mode 100755 tests/qemu-iotests/232
11
create mode 100755 tests/qemu-iotests/228
9
create mode 100644 tests/qemu-iotests/232.out
12
create mode 100644 tests/qemu-iotests/228.out
10
13
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
14
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
12
new file mode 100755
15
new file mode 100755
13
index XXXXXXX..XXXXXXX
16
index XXXXXXX..XXXXXXX
14
--- /dev/null
17
--- /dev/null
15
+++ b/tests/qemu-iotests/232
18
+++ b/tests/qemu-iotests/228
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
17
+#!/bin/bash
20
+#!/usr/bin/env python
18
+#
21
+#
19
+# Test for auto-read-only
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
20
+#
24
+#
21
+# Copyright (C) 2018 Red Hat, Inc.
25
+# Copyright (C) 2018 Red Hat, Inc.
22
+#
26
+#
23
+# This program is free software; you can redistribute it and/or modify
27
+# This program is free software; you can redistribute it and/or modify
24
+# it under the terms of the GNU General Public License as published by
28
+# it under the terms of the GNU General Public License as published by
...
...
31
+# GNU General Public License for more details.
35
+# GNU General Public License for more details.
32
+#
36
+#
33
+# You should have received a copy of the GNU General Public License
37
+# You should have received a copy of the GNU General Public License
34
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+#
39
+#
36
+
40
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
37
+# creator
41
+
38
+owner=kwolf@redhat.com
42
+import iotests
39
+
43
+from iotests import log, qemu_img, filter_testfiles, filter_imgfmt, \
40
+seq=`basename $0`
44
+ filter_qmp_testfiles, filter_qmp_imgfmt
41
+echo "QA output created by $seq"
45
+
42
+
46
+# Need backing file and change-backing-file support
43
+here=`pwd`
47
+iotests.verify_image_format(supported_fmts=['qcow2', 'qed'])
44
+status=1    # failure is the default!
48
+iotests.verify_platform(['linux'])
45
+
49
+
46
+_cleanup()
50
+
47
+{
51
+def log_node_info(node):
48
+ _cleanup_test_img
52
+ log('')
49
+ rm -f $TEST_IMG.snap
53
+
50
+}
54
+ log('bs->filename: ' + node['image']['filename'],
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
55
+ filters=[filter_testfiles, filter_imgfmt])
52
+
56
+ log('bs->backing_file: ' + node['backing_file'],
53
+# get standard environment, filters and checks
57
+ filters=[filter_testfiles, filter_imgfmt])
54
+. ./common.rc
58
+
55
+. ./common.filter
59
+ if 'backing-image' in node['image']:
56
+
60
+ log('bs->backing->bs->filename: ' +
57
+_supported_fmt generic
61
+ node['image']['backing-image']['filename'],
58
+_supported_proto file
62
+ filters=[filter_testfiles, filter_imgfmt])
59
+_supported_os Linux
63
+ else:
60
+
64
+ log('bs->backing: (none)')
61
+function do_run_qemu()
65
+
62
+{
66
+ log('')
63
+ echo Testing: "$@"
67
+
64
+ (
68
+
65
+ if ! test -t 0; then
69
+with iotests.FilePath('base.img') as base_img_path, \
66
+ while read cmd; do
70
+ iotests.FilePath('top.img') as top_img_path, \
67
+ echo $cmd
71
+ iotests.VM() as vm:
68
+ done
72
+
69
+ fi
73
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
70
+ echo quit
74
+ # Choose a funny way to describe the backing filename
71
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
75
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b',
72
+ echo
76
+ 'file:' + base_img_path, top_img_path) == 0
73
+}
77
+
74
+
78
+ vm.launch()
75
+function run_qemu()
79
+
76
+{
80
+ log('--- Implicit backing file ---')
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
81
+ log('')
78
+ _filter_generated_node_ids | _filter_imgfmt
82
+
79
+}
83
+ vm.qmp_log('blockdev-add',
80
+
84
+ node_name='node0',
81
+function run_qemu_info_block()
85
+ driver=iotests.imgfmt,
82
+{
86
+ file={
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
87
+ 'driver': 'file',
84
+}
88
+ 'filename': top_img_path
85
+
89
+ },
86
+size=128M
90
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
87
+
91
+
88
+_make_test_img $size
92
+ # Filename should be plain, and the backing filename should not
89
+
93
+ # contain the "file:" prefix
90
+echo
94
+ log_node_info(vm.node_info('node0'))
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
95
+
92
+echo
96
+ vm.qmp_log('blockdev-del', node_name='node0')
93
+
97
+
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
98
+ log('')
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
99
+ log('--- change-backing-file ---')
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
100
+ log('')
97
+echo
101
+
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
102
+ vm.qmp_log('blockdev-add',
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
103
+ node_name='node0',
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
104
+ driver=iotests.imgfmt,
101
+echo
105
+ file={
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
106
+ 'driver': 'file',
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
107
+ 'filename': top_img_path
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
108
+ },
105
+
109
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
106
+echo
110
+
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
111
+ # Changing the backing file to a qemu-reported filename should
108
+echo
112
+ # result in qemu accepting the corresponding BDS as the implicit
109
+
113
+ # backing BDS (and thus not generate a json:{} filename).
110
+chmod a-w $TEST_IMG
114
+ # So, first, query the backing filename.
111
+
115
+
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
116
+ backing_filename = \
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
117
+ vm.node_info('node0')['image']['backing-image']['filename']
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
118
+
115
+echo
119
+ # Next, change the backing file to something different
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
120
+
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
121
+ vm.qmp_log('change-backing-file',
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
122
+ image_node_name='node0',
119
+echo
123
+ device='node0',
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
124
+ backing_file='null-co://',
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
125
+ filters=[filter_qmp_testfiles])
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
126
+
123
+
127
+ # Now, verify that we get a json:{} filename
124
+echo
128
+ # (Image header says "null-co://", actual backing file still is
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
129
+ # base_img_path)
126
+echo
130
+
127
+
131
+ log_node_info(vm.node_info('node0'))
128
+chmod a+w $TEST_IMG
132
+
129
+
133
+ # Change it back
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
134
+ # (To get header and backing file in sync)
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
135
+
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
136
+ vm.qmp_log('change-backing-file',
133
+echo
137
+ image_node_name='node0',
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
138
+ device='node0',
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
139
+ backing_file=backing_filename,
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
140
+ filters=[filter_qmp_testfiles])
137
+echo
141
+
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
142
+ # And verify that we get our original results
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
143
+
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
144
+ log_node_info(vm.node_info('node0'))
141
+
145
+
142
+echo
146
+ # Finally, try a "file:" prefix. While this is actually what we
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
147
+ # originally had in the image header, qemu will not reopen the
144
+echo
148
+ # backing file here, so it cannot verify that this filename
145
+
149
+ # "resolves" to the actual backing BDS's filename and will thus
146
+chmod a-w $TEST_IMG
150
+ # consider both to be different.
147
+
151
+ # (This may be fixed in the future.)
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
152
+
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
153
+ vm.qmp_log('change-backing-file',
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
154
+ image_node_name='node0',
151
+echo
155
+ device='node0',
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
156
+ backing_file=('file:' + backing_filename),
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
157
+ filters=[filter_qmp_testfiles])
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
158
+
155
+echo
159
+ # So now we should get a json:{} filename
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
160
+
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
161
+ log_node_info(vm.node_info('node0'))
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
162
+
159
+
163
+ # Remove and re-attach so we can see that (as in our first try),
160
+# success, all done
164
+ # opening the image anew helps qemu resolve the header backing
161
+echo "*** done"
165
+ # filename.
162
+rm -f $seq.full
166
+
163
+status=0
167
+ vm.qmp_log('blockdev-del', node_name='node0')
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
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
165
new file mode 100644
263
new file mode 100644
166
index XXXXXXX..XXXXXXX
264
index XXXXXXX..XXXXXXX
167
--- /dev/null
265
--- /dev/null
168
+++ b/tests/qemu-iotests/232.out
266
+++ b/tests/qemu-iotests/228.out
169
@@ -XXX,XX +XXX,XX @@
267
@@ -XXX,XX +XXX,XX @@
170
+QA output created by 232
268
+--- Implicit backing file ---
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
269
+
172
+
270
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
271
+{"return": {}}
174
+
272
+
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
273
+bs->filename: TEST_DIR/PID-top.img
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
274
+bs->backing_file: TEST_DIR/PID-base.img
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
275
+bs->backing->bs->filename: TEST_DIR/PID-base.img
178
+
276
+
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
277
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
278
+{"return": {}}
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
279
+
182
+
280
+--- change-backing-file ---
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
281
+
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
282
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
283
+{"return": {}}
186
+
284
+{"execute": "change-backing-file", "arguments": {"backing-file": "null-co://", "device": "node0", "image-node-name": "node0"}}
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
285
+{"return": {}}
188
+
286
+
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
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"}}
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
288
+bs->backing_file: null-co://
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
289
+bs->backing->bs->filename: TEST_DIR/PID-base.img
192
+
290
+
193
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
291
+{"execute": "change-backing-file", "arguments": {"backing-file": "TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
292
+{"return": {}}
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
293
+
196
+
294
+bs->filename: TEST_DIR/PID-top.img
197
+QEMU_PROG: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
295
+bs->backing_file: TEST_DIR/PID-base.img
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
296
+bs->backing->bs->filename: TEST_DIR/PID-base.img
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
297
+
200
+
298
+{"execute": "change-backing-file", "arguments": {"backing-file": "file:TEST_DIR/PID-base.img", "device": "node0", "image-node-name": "node0"}}
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
299
+{"return": {}}
202
+
300
+
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
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"}}
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
302
+bs->backing_file: file:TEST_DIR/PID-base.img
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
303
+bs->backing->bs->filename: TEST_DIR/PID-base.img
206
+
304
+
207
+node0: TEST_DIR/t.IMGFMT (file)
305
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
208
+node0: TEST_DIR/t.IMGFMT (file)
306
+{"return": {}}
209
+node0: TEST_DIR/t.IMGFMT (file)
307
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
210
+
308
+{"return": {}}
211
+node0: TEST_DIR/t.IMGFMT (file)
309
+
212
+node0: TEST_DIR/t.IMGFMT (file)
310
+bs->filename: TEST_DIR/PID-top.img
213
+node0: TEST_DIR/t.IMGFMT (file)
311
+bs->backing_file: TEST_DIR/PID-base.img
214
+
312
+bs->backing->bs->filename: TEST_DIR/PID-base.img
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
313
+
216
+
314
+{"execute": "blockdev-del", "arguments": {"node-name": "node0"}}
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
315
+{"return": {}}
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
316
+
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
317
+--- Override backing file ---
220
+
318
+
221
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
319
+{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "null"}}
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
320
+{"return": {}}
223
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
321
+{"execute": "blockdev-add", "arguments": {"backing": "null", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "node0"}}
224
+
322
+{"return": {}}
225
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0,auto-read-only=off: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
323
+
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
324
+bs->filename: json:{"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
325
+bs->backing_file: null-co://
228
+*** done
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": {}}
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
352
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
230
index XXXXXXX..XXXXXXX 100644
353
index XXXXXXX..XXXXXXX 100644
231
--- a/tests/qemu-iotests/group
354
--- a/tests/qemu-iotests/group
232
+++ b/tests/qemu-iotests/group
355
+++ b/tests/qemu-iotests/group
233
@@ -XXX,XX +XXX,XX @@
356
@@ -XXX,XX +XXX,XX @@
357
225 rw auto quick
358
226 auto quick
234
227 auto quick
359
227 auto quick
360
+228 rw auto quick
235
229 auto quick
361
229 auto quick
236
231 auto quick
362
231 auto quick
237
+232 auto quick
363
232 auto quick
238
--
364
--
239
2.19.1
365
2.20.1
240
366
241
367
diff view generated by jsdifflib
1
If a management application builds the block graph node by node, the
1
From: Max Reitz <mreitz@redhat.com>
2
protocol layer doesn't inherit its read-only option from the format
3
layer any more, so it must be set explicitly.
4
2
5
Backing files should work on read-only storage, but at the same time, a
3
Besides being safe for arbitrary path lengths, after some follow-up
6
block job like commit should be able to reopen them read-write if they
4
patches all callers will want a freshly allocated buffer anyway.
7
are on read-write storage. However, without option inheritance, reopen
8
only changes the read-only option for the root node (typically the
9
format layer), but not the protocol layer, so reopening fails (the
10
format layer wants to get write permissions, but the protocol layer is
11
still read-only).
12
5
13
A simple workaround for the problem in the management tool would be to
6
In the meantime, path_combine_deprecated() is added which has the same
14
open the protocol layer always read-write and to make only the format
7
interface as path_combine() had before this patch. All callers to that
15
layer read-only for backing files. However, sometimes the file is
8
function will be converted in follow-up patches.
16
actually stored on read-only storage and we don't know whether the image
17
can be opened read-write (for example, for NBD it depends on the server
18
we're trying to connect to). This adds an option that makes QEMU try to
19
open the image read-write, but allows it to degrade to a read-only mode
20
without returning an error.
21
9
22
The documentation for this option is consciously phrased in a way that
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
allows QEMU to switch to a better model eventually: Instead of trying
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
24
when the image is first opened, making the read-only flag dynamic and
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
changing it automatically whenever the first BLK_PERM_WRITE user is
13
Message-id: 20190201192935.18394-10-mreitz@redhat.com
26
attached or the last one is detached would be much more useful
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
behaviour.
15
---
16
include/block/block.h | 4 +-
17
block.c | 85 ++++++++++++++++++++++++-------------------
18
block/vmdk.c | 3 +-
19
3 files changed, 49 insertions(+), 43 deletions(-)
28
20
29
Unfortunately, this more useful behaviour is also a lot harder to
30
implement, and libvirt needs a solution now before it can switch to
31
-blockdev, so let's start with this easier approach for now.
32
33
Instead of adding a new auto-read-only option, turning the existing
34
read-only into an enum (with a bool alternate for compatibility) was
35
considered, but it complicated the implementation to the point that it
36
didn't seem to be worth it.
37
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
40
---
41
qapi/block-core.json | 7 +++++++
42
include/block/block.h | 2 ++
43
block.c | 17 +++++++++++++++++
44
block/vvfat.c | 1 +
45
blockdev.c | 2 +-
46
5 files changed, 28 insertions(+), 1 deletion(-)
47
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
49
index XXXXXXX..XXXXXXX 100644
50
--- a/qapi/block-core.json
51
+++ b/qapi/block-core.json
52
@@ -XXX,XX +XXX,XX @@
53
# either generally or in certain configurations. In this case,
54
# the default value does not work and the option must be
55
# specified explicitly.
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
57
+# decide not to open the image read-write as requested, but
58
+# fall back to read-only instead (and switch between the modes
59
+# later), e.g. depending on whether the image file is writable
60
+# or whether a writing user is attached to the node
61
+# (default: false, since 3.1)
62
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
63
# (default: off)
64
# @force-share: force share all permission on added nodes.
65
@@ -XXX,XX +XXX,XX @@
66
'*discard': 'BlockdevDiscardOptions',
67
'*cache': 'BlockdevCacheOptions',
68
'*read-only': 'bool',
69
+ '*auto-read-only': 'bool',
70
'*force-share': 'bool',
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
72
'discriminator': 'driver',
73
diff --git a/include/block/block.h b/include/block/block.h
21
diff --git a/include/block/block.h b/include/block/block.h
74
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
75
--- a/include/block/block.h
23
--- a/include/block/block.h
76
+++ b/include/block/block.h
24
+++ b/include/block/block.h
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
25
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
78
select an appropriate protocol driver,
26
79
ignoring the format layer */
27
int path_has_protocol(const char *path);
80
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
28
int path_is_absolute(const char *path);
81
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
29
-void path_combine(char *dest, int dest_size,
82
30
- const char *base_path,
83
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
31
- const char *filename);
84
32
+char *path_combine(const char *base_path, const char *filename);
85
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
33
86
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
34
int bdrv_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
87
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
35
int bdrv_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
88
#define BDRV_OPT_READ_ONLY "read-only"
89
+#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
90
#define BDRV_OPT_DISCARD "discard"
91
#define BDRV_OPT_FORCE_SHARE "force-share"
92
93
diff --git a/block.c b/block.c
36
diff --git a/block.c b/block.c
94
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
95
--- a/block.c
38
--- a/block.c
96
+++ b/block.c
39
+++ b/block.c
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
40
@@ -XXX,XX +XXX,XX @@ int path_is_absolute(const char *path)
98
41
#endif
99
/* Inherit the read-only option from the parent if it's not set */
42
}
100
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
43
101
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
44
-/* if filename is absolute, just copy it to dest. Otherwise, build a
102
45
+/* if filename is absolute, just return its duplicate. Otherwise, build a
103
/* Our block drivers take care to send flushes and respect unmap policy,
46
path to it by considering it is relative to base_path. URL are
104
* so we can default to enable both on lower layers regardless of the
47
supported. */
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
48
-void path_combine(char *dest, int dest_size,
106
49
- const char *base_path,
107
/* backing files always opened read-only */
50
- const char *filename)
108
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
51
+char *path_combine(const char *base_path, const char *filename)
109
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
52
{
110
flags &= ~BDRV_O_COPY_ON_READ;
53
+ const char *protocol_stripped = NULL;
111
54
const char *p, *p1;
112
/* snapshot=on is handled on the top layer */
55
+ char *result;
113
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
56
int len;
114
*flags |= BDRV_O_RDWR;
57
58
- if (dest_size <= 0)
59
- return;
60
if (path_is_absolute(filename)) {
61
- pstrcpy(dest, dest_size, filename);
62
- } else {
63
- const char *protocol_stripped = NULL;
64
+ return g_strdup(filename);
65
+ }
66
67
- if (path_has_protocol(base_path)) {
68
- protocol_stripped = strchr(base_path, ':');
69
- if (protocol_stripped) {
70
- protocol_stripped++;
71
- }
72
+ if (path_has_protocol(base_path)) {
73
+ protocol_stripped = strchr(base_path, ':');
74
+ if (protocol_stripped) {
75
+ protocol_stripped++;
76
}
77
- p = protocol_stripped ?: base_path;
78
+ }
79
+ p = protocol_stripped ?: base_path;
80
81
- p1 = strrchr(base_path, '/');
82
+ p1 = strrchr(base_path, '/');
83
#ifdef _WIN32
84
- {
85
- const char *p2;
86
- p2 = strrchr(base_path, '\\');
87
- if (!p1 || p2 > p1)
88
- p1 = p2;
89
+ {
90
+ const char *p2;
91
+ p2 = strrchr(base_path, '\\');
92
+ if (!p1 || p2 > p1) {
93
+ p1 = p2;
94
}
95
+ }
96
#endif
97
- if (p1)
98
- p1++;
99
- else
100
- p1 = base_path;
101
- if (p1 > p)
102
- p = p1;
103
- len = p - base_path;
104
- if (len > dest_size - 1)
105
- len = dest_size - 1;
106
- memcpy(dest, base_path, len);
107
- dest[len] = '\0';
108
- pstrcat(dest, dest_size, filename);
109
+ if (p1) {
110
+ p1++;
111
+ } else {
112
+ p1 = base_path;
113
+ }
114
+ if (p1 > p) {
115
+ p = p1;
115
}
116
}
116
117
+ len = p - base_path;
117
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
118
+
118
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
119
+ result = g_malloc(len + strlen(filename) + 1);
119
+ *flags |= BDRV_O_AUTO_RDONLY;
120
+ memcpy(result, base_path, len);
120
+ }
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);
121
}
133
}
122
134
123
static void update_options_from_flags(QDict *options, int flags)
135
/*
124
@@ -XXX,XX +XXX,XX @@ static void update_options_from_flags(QDict *options, int flags)
136
@@ -XXX,XX +XXX,XX @@ void bdrv_get_full_backing_filename_from_filename(const char *backed,
125
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
137
error_setg(errp, "Cannot use relative backing file names for '%s'",
126
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
138
backed);
139
} else {
140
- path_combine(dest, sz, backed, backing);
141
+ path_combine_deprecated(dest, sz, backed, backing);
127
}
142
}
128
+ if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
129
+ qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
130
+ flags & BDRV_O_AUTO_RDONLY);
131
+ }
132
}
143
}
133
144
134
static void bdrv_assign_node_name(BlockDriverState *bs,
145
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
135
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
146
} else {
136
.type = QEMU_OPT_BOOL,
147
/* If not an absolute filename path, make it relative to the current
137
.help = "Node is opened in read-only mode",
148
* image's filename path */
138
},
149
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
139
+ {
150
- backing_file);
140
+ .name = BDRV_OPT_AUTO_READ_ONLY,
151
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
141
+ .type = QEMU_OPT_BOOL,
152
+ backing_file);
142
+ .help = "Node can become read-only if opening read-write fails",
153
143
+ },
154
/* We are going to compare absolute pathnames */
144
{
155
if (!realpath(filename_tmp, filename_full)) {
145
.name = "detect-zeroes",
156
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
146
.type = QEMU_OPT_STRING,
157
147
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
158
/* We need to make sure the backing filename we are comparing against
148
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
159
* is relative to the current image filename (or absolute) */
149
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
160
- path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
150
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
161
- curr_bs->backing_file);
151
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
162
+ path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
152
+
163
+ curr_bs->backing_file);
153
}
164
154
165
if (!realpath(filename_tmp, backing_file_full)) {
155
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
166
continue;
156
diff --git a/block/vvfat.c b/block/vvfat.c
167
diff --git a/block/vmdk.c b/block/vmdk.c
157
index XXXXXXX..XXXXXXX 100644
168
index XXXXXXX..XXXXXXX 100644
158
--- a/block/vvfat.c
169
--- a/block/vmdk.c
159
+++ b/block/vvfat.c
170
+++ b/block/vmdk.c
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
171
@@ -XXX,XX +XXX,XX @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
161
int parent_flags, QDict *parent_options)
172
return -EINVAL;
162
{
173
}
163
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
174
164
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
175
- extent_path = g_malloc0(PATH_MAX);
165
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
176
- path_combine(extent_path, PATH_MAX, desc_file_path, fname);
166
}
177
+ extent_path = path_combine(desc_file_path, fname);
167
178
168
diff --git a/blockdev.c b/blockdev.c
179
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
169
index XXXXXXX..XXXXXXX 100644
180
assert(ret < 32);
170
--- a/blockdev.c
171
+++ b/blockdev.c
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
173
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
176
- BDRV_O_PROTOCOL);
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
178
179
if (!has_read_only) {
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
181
--
181
--
182
2.19.1
182
2.20.1
183
183
184
184
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This adds some whitespace into the option help (including indentation)
3
Make bdrv_get_full_backing_filename_from_filename() return an allocated
4
and puts angle brackets around the type names. Furthermore, the list
4
string instead of placing the result in a caller-provided buffer.
5
name is no longer printed as part of every line, but only once in
6
advance, and only if the caller did not print a caption already.
7
8
This patch also restores the description alignment we had before commit
9
9cbef9d68ee1d8d0, just at 24 instead of 16 characters like we used to.
10
This increase is because now we have the type and two spaces of
11
indentation before the description, and with a usual type name length of
12
three chracters, this sums up to eight additional characters -- which
13
means that we now need 24 characters to get the same amount of padding
14
for most options. Also, 24 is a third of 80, which makes it kind of a
15
round number in terminal terms.
16
17
Finally, this patch amends the reference output of iotest 082 to match
18
the changes (and thus makes it pass again).
19
5
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
7
Message-id: 20190201192935.18394-11-mreitz@redhat.com
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
9
---
24
include/qemu/option.h | 2 +-
10
include/block/block.h | 7 +++---
25
qemu-img.c | 4 +-
11
block.c | 53 ++++++++++++++++++++++++++++++-------------
26
util/qemu-option.c | 32 +-
12
block/vmdk.c | 10 ++++----
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
13
qemu-img.c | 12 ++++------
28
4 files changed, 507 insertions(+), 487 deletions(-)
14
4 files changed, 49 insertions(+), 33 deletions(-)
29
15
30
diff --git a/include/qemu/option.h b/include/qemu/option.h
16
diff --git a/include/block/block.h b/include/block/block.h
31
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
32
--- a/include/qemu/option.h
18
--- a/include/block/block.h
33
+++ b/include/qemu/option.h
19
+++ b/include/block/block.h
34
@@ -XXX,XX +XXX,XX @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
20
@@ -XXX,XX +XXX,XX @@ void bdrv_get_backing_filename(BlockDriverState *bs,
35
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
21
char *filename, int filename_size);
36
void *opaque, Error **errp);
22
void bdrv_get_full_backing_filename(BlockDriverState *bs,
37
void qemu_opts_print(QemuOpts *opts, const char *sep);
23
char *dest, size_t sz, Error **errp);
38
-void qemu_opts_print_help(QemuOptsList *list);
24
-void bdrv_get_full_backing_filename_from_filename(const char *backed,
39
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
25
- const char *backing,
40
void qemu_opts_free(QemuOptsList *list);
26
- char *dest, size_t sz,
41
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
27
- Error **errp);
42
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
+/*
47
+ * If @backing is empty, this function returns NULL without setting
48
+ * @errp. In all other cases, NULL will only be returned with @errp
49
+ * set.
50
+ *
51
+ * Therefore, a return value of NULL without @errp set means that
52
+ * there is no backing file; if @errp is set, there is one but its
53
+ * absolute filename cannot be generated.
54
+ */
55
+char *bdrv_get_full_backing_filename_from_filename(const char *backed,
56
+ const char *backing,
57
+ Error **errp)
58
{
59
- if (backing[0] == '\0' || path_has_protocol(backing) ||
60
- path_is_absolute(backing))
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
+
90
+ full_name = bdrv_get_full_backing_filename_from_filename(backed,
91
+ bs->backing_file,
92
+ &local_error);
93
+ if (full_name) {
94
+ pstrcpy(dest, sz, full_name);
95
+ g_free(full_name);
96
+ } else if (local_error) {
97
+ error_propagate(errp, local_error);
98
+ } else if (sz > 0) {
99
+ *dest = '\0';
100
+ }
101
}
102
103
void bdrv_register(BlockDriver *bdrv)
104
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
105
size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, img_size);
106
if (backing_file && !(flags & BDRV_O_NO_BACKING)) {
107
BlockDriverState *bs;
108
- char *full_backing = g_new0(char, PATH_MAX);
109
+ char *full_backing;
110
int back_flags;
111
QDict *backing_options = NULL;
112
113
- bdrv_get_full_backing_filename_from_filename(filename, backing_file,
114
- full_backing, PATH_MAX,
115
- &local_err);
116
+ full_backing =
117
+ bdrv_get_full_backing_filename_from_filename(filename, backing_file,
118
+ &local_err);
119
if (local_err) {
120
- g_free(full_backing);
121
goto out;
122
}
123
+ assert(full_backing);
124
125
/* backing files always opened read-only */
126
back_flags = flags;
127
diff --git a/block/vmdk.c b/block/vmdk.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/block/vmdk.c
130
+++ b/block/vmdk.c
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
132
133
if (backing_file) {
134
BlockBackend *backing;
135
- char *full_backing = g_new0(char, PATH_MAX);
136
- bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename, backing_file,
137
- full_backing, PATH_MAX,
138
- &local_err);
139
+ char *full_backing =
140
+ bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename,
141
+ backing_file,
142
+ &local_err);
143
if (local_err) {
144
- g_free(full_backing);
145
error_propagate(errp, local_err);
146
ret = -ENOENT;
147
goto exit;
148
}
149
+ assert(full_backing);
150
151
backing = blk_new_open(full_backing, NULL, NULL,
152
BDRV_O_NO_BACKING, errp);
43
diff --git a/qemu-img.c b/qemu-img.c
153
diff --git a/qemu-img.c b/qemu-img.c
44
index XXXXXXX..XXXXXXX 100644
154
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-img.c
155
--- a/qemu-img.c
46
+++ b/qemu-img.c
156
+++ b/qemu-img.c
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
157
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
48
}
158
bdrv_refresh_filename(bs);
49
159
overlay_filename = bs->exact_filename[0] ? bs->exact_filename
50
printf("Supported options:\n");
160
: bs->filename;
51
- qemu_opts_print_help(create_opts);
161
- out_real_path = g_malloc(PATH_MAX);
52
+ qemu_opts_print_help(create_opts, false);
162
-
53
qemu_opts_free(create_opts);
163
- bdrv_get_full_backing_filename_from_filename(overlay_filename,
54
return 0;
164
- out_baseimg,
55
}
165
- out_real_path,
56
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
166
- PATH_MAX,
57
assert(drv->create_opts);
167
- &local_err);
58
168
+ out_real_path =
59
printf("Creation options for '%s':\n", format);
169
+ bdrv_get_full_backing_filename_from_filename(overlay_filename,
60
- qemu_opts_print_help(drv->create_opts);
170
+ out_baseimg,
61
+ qemu_opts_print_help(drv->create_opts, false);
171
+ &local_err);
62
printf("\nNote that not all of these options may be amendable.\n");
172
if (local_err) {
63
return 0;
173
error_reportf_err(local_err,
64
}
174
"Could not resolve backing filename: ");
65
diff --git a/util/qemu-option.c b/util/qemu-option.c
175
ret = -1;
66
index XXXXXXX..XXXXXXX 100644
176
- g_free(out_real_path);
67
--- a/util/qemu-option.c
177
goto out;
68
+++ b/util/qemu-option.c
178
}
69
@@ -XXX,XX +XXX,XX @@ static const char *opt_type_to_string(enum QemuOptType type)
179
70
g_assert_not_reached();
71
}
72
73
-void qemu_opts_print_help(QemuOptsList *list)
74
+/**
75
+ * Print the list of options available in the given list. If
76
+ * @print_caption is true, a caption (including the list name, if it
77
+ * exists) is printed. The options itself will be indented, so
78
+ * @print_caption should only be set to false if the caller prints its
79
+ * own custom caption (so that the indentation makes sense).
80
+ */
81
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
82
{
83
QemuOptDesc *desc;
84
int i;
85
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
86
desc = list->desc;
87
while (desc && desc->name) {
88
GString *str = g_string_new(NULL);
89
- if (list->name) {
90
- g_string_append_printf(str, "%s.", list->name);
91
- }
92
- g_string_append_printf(str, "%s=%s", desc->name,
93
+ g_string_append_printf(str, " %s=<%s>", desc->name,
94
opt_type_to_string(desc->type));
95
if (desc->help) {
96
+ if (str->len < 24) {
97
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
98
+ }
99
g_string_append_printf(str, " - %s", desc->help);
100
}
101
g_ptr_array_add(array, g_string_free(str, false));
102
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
103
}
104
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
106
+ if (print_caption && array->len > 0) {
107
+ if (list->name) {
108
+ printf("%s options:\n", list->name);
109
+ } else {
110
+ printf("Options:\n");
111
+ }
112
+ } else if (array->len == 0) {
113
+ if (list->name) {
114
+ printf("There are no options for %s.\n", list->name);
115
+ } else {
116
+ printf("No options available.\n");
117
+ }
118
+ }
119
for (i = 0; i < array->len; i++) {
120
printf("%s\n", (char *)array->pdata[i]);
121
}
122
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
123
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
124
if (err) {
125
if (invalidp && has_help_option(params)) {
126
- qemu_opts_print_help(list);
127
+ qemu_opts_print_help(list, true);
128
error_free(err);
129
} else {
130
error_report_err(err);
131
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
132
index XXXXXXX..XXXXXXX 100644
133
--- a/tests/qemu-iotests/082.out
134
+++ b/tests/qemu-iotests/082.out
135
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
136
137
Testing: create -f qcow2 -o help TEST_DIR/t.qcow2 128M
138
Supported options:
139
-size Virtual disk size
140
-compat Compatibility level (0.10 or 1.1)
141
-backing_file File name of a base image
142
-backing_fmt Image format of the base image
143
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
144
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
145
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
146
-encrypt.cipher-alg Name of encryption cipher algorithm
147
-encrypt.cipher-mode Name of encryption cipher mode
148
-encrypt.ivgen-alg Name of IV generator algorithm
149
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
150
-encrypt.hash-alg Name of encryption hash algorithm
151
-encrypt.iter-time Time to spend in PBKDF in milliseconds
152
-cluster_size qcow2 cluster size
153
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
154
-lazy_refcounts Postpone refcount updates
155
-refcount_bits Width of a reference count entry in bits
156
-nocow Turn off copy-on-write (valid only on btrfs)
157
+ backing_file=<str> - File name of a base image
158
+ backing_fmt=<str> - Image format of the base image
159
+ cluster_size=<size> - qcow2 cluster size
160
+ compat=<str> - Compatibility level (0.10 or 1.1)
161
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
162
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
163
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
164
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
165
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
166
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
167
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
168
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
169
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
170
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
171
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
172
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
173
+ refcount_bits=<num> - Width of a reference count entry in bits
174
+ size=<size> - Virtual disk size
175
176
Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
177
Supported options:
178
-size Virtual disk size
179
-compat Compatibility level (0.10 or 1.1)
180
-backing_file File name of a base image
181
-backing_fmt Image format of the base image
182
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
183
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
184
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
185
-encrypt.cipher-alg Name of encryption cipher algorithm
186
-encrypt.cipher-mode Name of encryption cipher mode
187
-encrypt.ivgen-alg Name of IV generator algorithm
188
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
189
-encrypt.hash-alg Name of encryption hash algorithm
190
-encrypt.iter-time Time to spend in PBKDF in milliseconds
191
-cluster_size qcow2 cluster size
192
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
193
-lazy_refcounts Postpone refcount updates
194
-refcount_bits Width of a reference count entry in bits
195
-nocow Turn off copy-on-write (valid only on btrfs)
196
+ backing_file=<str> - File name of a base image
197
+ backing_fmt=<str> - Image format of the base image
198
+ cluster_size=<size> - qcow2 cluster size
199
+ compat=<str> - Compatibility level (0.10 or 1.1)
200
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
201
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
202
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
203
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
204
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
205
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
206
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
207
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
208
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
209
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
210
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
211
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
212
+ refcount_bits=<num> - Width of a reference count entry in bits
213
+ size=<size> - Virtual disk size
214
215
Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
216
Supported options:
217
-size Virtual disk size
218
-compat Compatibility level (0.10 or 1.1)
219
-backing_file File name of a base image
220
-backing_fmt Image format of the base image
221
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
222
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
223
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
224
-encrypt.cipher-alg Name of encryption cipher algorithm
225
-encrypt.cipher-mode Name of encryption cipher mode
226
-encrypt.ivgen-alg Name of IV generator algorithm
227
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
228
-encrypt.hash-alg Name of encryption hash algorithm
229
-encrypt.iter-time Time to spend in PBKDF in milliseconds
230
-cluster_size qcow2 cluster size
231
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
232
-lazy_refcounts Postpone refcount updates
233
-refcount_bits Width of a reference count entry in bits
234
-nocow Turn off copy-on-write (valid only on btrfs)
235
+ backing_file=<str> - File name of a base image
236
+ backing_fmt=<str> - Image format of the base image
237
+ cluster_size=<size> - qcow2 cluster size
238
+ compat=<str> - Compatibility level (0.10 or 1.1)
239
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
240
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
241
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
242
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
243
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
244
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
245
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
246
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
247
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
248
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
249
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
250
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
251
+ refcount_bits=<num> - Width of a reference count entry in bits
252
+ size=<size> - Virtual disk size
253
254
Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
255
Supported options:
256
-size Virtual disk size
257
-compat Compatibility level (0.10 or 1.1)
258
-backing_file File name of a base image
259
-backing_fmt Image format of the base image
260
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
261
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
262
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
263
-encrypt.cipher-alg Name of encryption cipher algorithm
264
-encrypt.cipher-mode Name of encryption cipher mode
265
-encrypt.ivgen-alg Name of IV generator algorithm
266
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
267
-encrypt.hash-alg Name of encryption hash algorithm
268
-encrypt.iter-time Time to spend in PBKDF in milliseconds
269
-cluster_size qcow2 cluster size
270
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
271
-lazy_refcounts Postpone refcount updates
272
-refcount_bits Width of a reference count entry in bits
273
-nocow Turn off copy-on-write (valid only on btrfs)
274
+ backing_file=<str> - File name of a base image
275
+ backing_fmt=<str> - Image format of the base image
276
+ cluster_size=<size> - qcow2 cluster size
277
+ compat=<str> - Compatibility level (0.10 or 1.1)
278
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
279
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
280
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
281
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
282
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
283
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
284
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
285
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
286
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
287
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
288
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
289
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
290
+ refcount_bits=<num> - Width of a reference count entry in bits
291
+ size=<size> - Virtual disk size
292
293
Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
294
Supported options:
295
-size Virtual disk size
296
-compat Compatibility level (0.10 or 1.1)
297
-backing_file File name of a base image
298
-backing_fmt Image format of the base image
299
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
300
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
301
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
302
-encrypt.cipher-alg Name of encryption cipher algorithm
303
-encrypt.cipher-mode Name of encryption cipher mode
304
-encrypt.ivgen-alg Name of IV generator algorithm
305
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
306
-encrypt.hash-alg Name of encryption hash algorithm
307
-encrypt.iter-time Time to spend in PBKDF in milliseconds
308
-cluster_size qcow2 cluster size
309
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
310
-lazy_refcounts Postpone refcount updates
311
-refcount_bits Width of a reference count entry in bits
312
-nocow Turn off copy-on-write (valid only on btrfs)
313
+ backing_file=<str> - File name of a base image
314
+ backing_fmt=<str> - Image format of the base image
315
+ cluster_size=<size> - qcow2 cluster size
316
+ compat=<str> - Compatibility level (0.10 or 1.1)
317
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
318
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
319
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
320
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
321
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
322
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
323
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
324
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
325
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
326
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
327
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
328
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
329
+ refcount_bits=<num> - Width of a reference count entry in bits
330
+ size=<size> - Virtual disk size
331
332
Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
333
Supported options:
334
-size Virtual disk size
335
-compat Compatibility level (0.10 or 1.1)
336
-backing_file File name of a base image
337
-backing_fmt Image format of the base image
338
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
339
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
340
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
341
-encrypt.cipher-alg Name of encryption cipher algorithm
342
-encrypt.cipher-mode Name of encryption cipher mode
343
-encrypt.ivgen-alg Name of IV generator algorithm
344
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
345
-encrypt.hash-alg Name of encryption hash algorithm
346
-encrypt.iter-time Time to spend in PBKDF in milliseconds
347
-cluster_size qcow2 cluster size
348
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
349
-lazy_refcounts Postpone refcount updates
350
-refcount_bits Width of a reference count entry in bits
351
-nocow Turn off copy-on-write (valid only on btrfs)
352
+ backing_file=<str> - File name of a base image
353
+ backing_fmt=<str> - Image format of the base image
354
+ cluster_size=<size> - qcow2 cluster size
355
+ compat=<str> - Compatibility level (0.10 or 1.1)
356
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
357
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
358
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
359
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
360
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
361
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
362
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
363
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
364
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
365
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
366
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
367
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
368
+ refcount_bits=<num> - Width of a reference count entry in bits
369
+ size=<size> - Virtual disk size
370
371
Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
372
Supported options:
373
-size Virtual disk size
374
-compat Compatibility level (0.10 or 1.1)
375
-backing_file File name of a base image
376
-backing_fmt Image format of the base image
377
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
378
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
379
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
380
-encrypt.cipher-alg Name of encryption cipher algorithm
381
-encrypt.cipher-mode Name of encryption cipher mode
382
-encrypt.ivgen-alg Name of IV generator algorithm
383
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
384
-encrypt.hash-alg Name of encryption hash algorithm
385
-encrypt.iter-time Time to spend in PBKDF in milliseconds
386
-cluster_size qcow2 cluster size
387
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
388
-lazy_refcounts Postpone refcount updates
389
-refcount_bits Width of a reference count entry in bits
390
-nocow Turn off copy-on-write (valid only on btrfs)
391
+ backing_file=<str> - File name of a base image
392
+ backing_fmt=<str> - Image format of the base image
393
+ cluster_size=<size> - qcow2 cluster size
394
+ compat=<str> - Compatibility level (0.10 or 1.1)
395
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
396
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
397
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
398
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
399
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
400
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
401
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
402
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
403
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
404
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
405
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
406
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
407
+ refcount_bits=<num> - Width of a reference count entry in bits
408
+ size=<size> - Virtual disk size
409
410
Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
411
Supported options:
412
-size Virtual disk size
413
-compat Compatibility level (0.10 or 1.1)
414
-backing_file File name of a base image
415
-backing_fmt Image format of the base image
416
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
417
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
418
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
419
-encrypt.cipher-alg Name of encryption cipher algorithm
420
-encrypt.cipher-mode Name of encryption cipher mode
421
-encrypt.ivgen-alg Name of IV generator algorithm
422
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
423
-encrypt.hash-alg Name of encryption hash algorithm
424
-encrypt.iter-time Time to spend in PBKDF in milliseconds
425
-cluster_size qcow2 cluster size
426
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
427
-lazy_refcounts Postpone refcount updates
428
-refcount_bits Width of a reference count entry in bits
429
-nocow Turn off copy-on-write (valid only on btrfs)
430
+ backing_file=<str> - File name of a base image
431
+ backing_fmt=<str> - Image format of the base image
432
+ cluster_size=<size> - qcow2 cluster size
433
+ compat=<str> - Compatibility level (0.10 or 1.1)
434
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
435
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
436
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
437
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
438
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
439
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
440
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
441
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
442
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
443
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
444
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
445
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
446
+ refcount_bits=<num> - Width of a reference count entry in bits
447
+ size=<size> - Virtual disk size
448
449
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
450
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16
451
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
452
453
Testing: create -f qcow2 -o help
454
Supported options:
455
-size Virtual disk size
456
-compat Compatibility level (0.10 or 1.1)
457
-backing_file File name of a base image
458
-backing_fmt Image format of the base image
459
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
460
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
461
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
462
-encrypt.cipher-alg Name of encryption cipher algorithm
463
-encrypt.cipher-mode Name of encryption cipher mode
464
-encrypt.ivgen-alg Name of IV generator algorithm
465
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
466
-encrypt.hash-alg Name of encryption hash algorithm
467
-encrypt.iter-time Time to spend in PBKDF in milliseconds
468
-cluster_size qcow2 cluster size
469
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
470
-lazy_refcounts Postpone refcount updates
471
-refcount_bits Width of a reference count entry in bits
472
+ backing_file=<str> - File name of a base image
473
+ backing_fmt=<str> - Image format of the base image
474
+ cluster_size=<size> - qcow2 cluster size
475
+ compat=<str> - Compatibility level (0.10 or 1.1)
476
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
477
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
478
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
479
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
480
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
481
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
482
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
483
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
484
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
485
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
486
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
487
+ refcount_bits=<num> - Width of a reference count entry in bits
488
+ size=<size> - Virtual disk size
489
490
Testing: create -o help
491
Supported options:
492
-size Virtual disk size
493
+ size=<size> - Virtual disk size
494
495
Testing: create -f bochs -o help
496
qemu-img: Format driver 'bochs' does not support image creation
497
@@ -XXX,XX +XXX,XX @@ cluster_size: 8192
498
499
Testing: convert -O qcow2 -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
500
Supported options:
501
-size Virtual disk size
502
-compat Compatibility level (0.10 or 1.1)
503
-backing_file File name of a base image
504
-backing_fmt Image format of the base image
505
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
506
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
507
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
508
-encrypt.cipher-alg Name of encryption cipher algorithm
509
-encrypt.cipher-mode Name of encryption cipher mode
510
-encrypt.ivgen-alg Name of IV generator algorithm
511
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
512
-encrypt.hash-alg Name of encryption hash algorithm
513
-encrypt.iter-time Time to spend in PBKDF in milliseconds
514
-cluster_size qcow2 cluster size
515
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
516
-lazy_refcounts Postpone refcount updates
517
-refcount_bits Width of a reference count entry in bits
518
-nocow Turn off copy-on-write (valid only on btrfs)
519
+ backing_file=<str> - File name of a base image
520
+ backing_fmt=<str> - Image format of the base image
521
+ cluster_size=<size> - qcow2 cluster size
522
+ compat=<str> - Compatibility level (0.10 or 1.1)
523
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
524
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
525
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
526
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
527
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
528
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
529
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
530
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
531
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
532
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
533
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
534
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
535
+ refcount_bits=<num> - Width of a reference count entry in bits
536
+ size=<size> - Virtual disk size
537
538
Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
539
Supported options:
540
-size Virtual disk size
541
-compat Compatibility level (0.10 or 1.1)
542
-backing_file File name of a base image
543
-backing_fmt Image format of the base image
544
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
545
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
546
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
547
-encrypt.cipher-alg Name of encryption cipher algorithm
548
-encrypt.cipher-mode Name of encryption cipher mode
549
-encrypt.ivgen-alg Name of IV generator algorithm
550
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
551
-encrypt.hash-alg Name of encryption hash algorithm
552
-encrypt.iter-time Time to spend in PBKDF in milliseconds
553
-cluster_size qcow2 cluster size
554
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
555
-lazy_refcounts Postpone refcount updates
556
-refcount_bits Width of a reference count entry in bits
557
-nocow Turn off copy-on-write (valid only on btrfs)
558
+ backing_file=<str> - File name of a base image
559
+ backing_fmt=<str> - Image format of the base image
560
+ cluster_size=<size> - qcow2 cluster size
561
+ compat=<str> - Compatibility level (0.10 or 1.1)
562
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
563
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
564
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
565
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
566
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
567
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
568
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
569
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
570
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
571
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
572
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
573
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
574
+ refcount_bits=<num> - Width of a reference count entry in bits
575
+ size=<size> - Virtual disk size
576
577
Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
578
Supported options:
579
-size Virtual disk size
580
-compat Compatibility level (0.10 or 1.1)
581
-backing_file File name of a base image
582
-backing_fmt Image format of the base image
583
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
584
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
585
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
586
-encrypt.cipher-alg Name of encryption cipher algorithm
587
-encrypt.cipher-mode Name of encryption cipher mode
588
-encrypt.ivgen-alg Name of IV generator algorithm
589
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
590
-encrypt.hash-alg Name of encryption hash algorithm
591
-encrypt.iter-time Time to spend in PBKDF in milliseconds
592
-cluster_size qcow2 cluster size
593
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
594
-lazy_refcounts Postpone refcount updates
595
-refcount_bits Width of a reference count entry in bits
596
-nocow Turn off copy-on-write (valid only on btrfs)
597
+ backing_file=<str> - File name of a base image
598
+ backing_fmt=<str> - Image format of the base image
599
+ cluster_size=<size> - qcow2 cluster size
600
+ compat=<str> - Compatibility level (0.10 or 1.1)
601
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
602
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
603
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
604
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
605
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
606
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
607
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
608
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
609
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
610
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
611
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
612
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
613
+ refcount_bits=<num> - Width of a reference count entry in bits
614
+ size=<size> - Virtual disk size
615
616
Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
617
Supported options:
618
-size Virtual disk size
619
-compat Compatibility level (0.10 or 1.1)
620
-backing_file File name of a base image
621
-backing_fmt Image format of the base image
622
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
623
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
624
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
625
-encrypt.cipher-alg Name of encryption cipher algorithm
626
-encrypt.cipher-mode Name of encryption cipher mode
627
-encrypt.ivgen-alg Name of IV generator algorithm
628
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
629
-encrypt.hash-alg Name of encryption hash algorithm
630
-encrypt.iter-time Time to spend in PBKDF in milliseconds
631
-cluster_size qcow2 cluster size
632
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
633
-lazy_refcounts Postpone refcount updates
634
-refcount_bits Width of a reference count entry in bits
635
-nocow Turn off copy-on-write (valid only on btrfs)
636
+ backing_file=<str> - File name of a base image
637
+ backing_fmt=<str> - Image format of the base image
638
+ cluster_size=<size> - qcow2 cluster size
639
+ compat=<str> - Compatibility level (0.10 or 1.1)
640
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
641
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
642
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
643
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
644
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
645
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
646
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
647
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
648
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
649
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
650
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
651
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
652
+ refcount_bits=<num> - Width of a reference count entry in bits
653
+ size=<size> - Virtual disk size
654
655
Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
656
Supported options:
657
-size Virtual disk size
658
-compat Compatibility level (0.10 or 1.1)
659
-backing_file File name of a base image
660
-backing_fmt Image format of the base image
661
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
662
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
663
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
664
-encrypt.cipher-alg Name of encryption cipher algorithm
665
-encrypt.cipher-mode Name of encryption cipher mode
666
-encrypt.ivgen-alg Name of IV generator algorithm
667
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
668
-encrypt.hash-alg Name of encryption hash algorithm
669
-encrypt.iter-time Time to spend in PBKDF in milliseconds
670
-cluster_size qcow2 cluster size
671
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
672
-lazy_refcounts Postpone refcount updates
673
-refcount_bits Width of a reference count entry in bits
674
-nocow Turn off copy-on-write (valid only on btrfs)
675
+ backing_file=<str> - File name of a base image
676
+ backing_fmt=<str> - Image format of the base image
677
+ cluster_size=<size> - qcow2 cluster size
678
+ compat=<str> - Compatibility level (0.10 or 1.1)
679
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
680
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
681
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
682
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
683
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
684
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
685
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
686
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
687
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
688
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
689
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
690
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
691
+ refcount_bits=<num> - Width of a reference count entry in bits
692
+ size=<size> - Virtual disk size
693
694
Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
695
Supported options:
696
-size Virtual disk size
697
-compat Compatibility level (0.10 or 1.1)
698
-backing_file File name of a base image
699
-backing_fmt Image format of the base image
700
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
701
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
702
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
703
-encrypt.cipher-alg Name of encryption cipher algorithm
704
-encrypt.cipher-mode Name of encryption cipher mode
705
-encrypt.ivgen-alg Name of IV generator algorithm
706
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
707
-encrypt.hash-alg Name of encryption hash algorithm
708
-encrypt.iter-time Time to spend in PBKDF in milliseconds
709
-cluster_size qcow2 cluster size
710
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
711
-lazy_refcounts Postpone refcount updates
712
-refcount_bits Width of a reference count entry in bits
713
-nocow Turn off copy-on-write (valid only on btrfs)
714
+ backing_file=<str> - File name of a base image
715
+ backing_fmt=<str> - Image format of the base image
716
+ cluster_size=<size> - qcow2 cluster size
717
+ compat=<str> - Compatibility level (0.10 or 1.1)
718
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
719
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
720
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
721
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
722
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
723
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
724
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
725
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
726
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
727
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
728
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
729
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
730
+ refcount_bits=<num> - Width of a reference count entry in bits
731
+ size=<size> - Virtual disk size
732
733
Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
734
Supported options:
735
-size Virtual disk size
736
-compat Compatibility level (0.10 or 1.1)
737
-backing_file File name of a base image
738
-backing_fmt Image format of the base image
739
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
740
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
741
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
742
-encrypt.cipher-alg Name of encryption cipher algorithm
743
-encrypt.cipher-mode Name of encryption cipher mode
744
-encrypt.ivgen-alg Name of IV generator algorithm
745
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
746
-encrypt.hash-alg Name of encryption hash algorithm
747
-encrypt.iter-time Time to spend in PBKDF in milliseconds
748
-cluster_size qcow2 cluster size
749
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
750
-lazy_refcounts Postpone refcount updates
751
-refcount_bits Width of a reference count entry in bits
752
-nocow Turn off copy-on-write (valid only on btrfs)
753
+ backing_file=<str> - File name of a base image
754
+ backing_fmt=<str> - Image format of the base image
755
+ cluster_size=<size> - qcow2 cluster size
756
+ compat=<str> - Compatibility level (0.10 or 1.1)
757
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
758
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
759
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
760
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
761
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
762
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
763
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
764
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
765
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
766
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
767
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
768
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
769
+ refcount_bits=<num> - Width of a reference count entry in bits
770
+ size=<size> - Virtual disk size
771
772
Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
773
Supported options:
774
-size Virtual disk size
775
-compat Compatibility level (0.10 or 1.1)
776
-backing_file File name of a base image
777
-backing_fmt Image format of the base image
778
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
779
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
780
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
781
-encrypt.cipher-alg Name of encryption cipher algorithm
782
-encrypt.cipher-mode Name of encryption cipher mode
783
-encrypt.ivgen-alg Name of IV generator algorithm
784
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
785
-encrypt.hash-alg Name of encryption hash algorithm
786
-encrypt.iter-time Time to spend in PBKDF in milliseconds
787
-cluster_size qcow2 cluster size
788
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
789
-lazy_refcounts Postpone refcount updates
790
-refcount_bits Width of a reference count entry in bits
791
-nocow Turn off copy-on-write (valid only on btrfs)
792
+ backing_file=<str> - File name of a base image
793
+ backing_fmt=<str> - Image format of the base image
794
+ cluster_size=<size> - qcow2 cluster size
795
+ compat=<str> - Compatibility level (0.10 or 1.1)
796
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
797
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
798
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
799
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
800
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
801
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
802
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
803
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
804
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
805
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
806
+ nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
807
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
808
+ refcount_bits=<num> - Width of a reference count entry in bits
809
+ size=<size> - Virtual disk size
810
811
Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
812
qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory
813
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
814
815
Testing: convert -O qcow2 -o help
816
Supported options:
817
-size Virtual disk size
818
-compat Compatibility level (0.10 or 1.1)
819
-backing_file File name of a base image
820
-backing_fmt Image format of the base image
821
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
822
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
823
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
824
-encrypt.cipher-alg Name of encryption cipher algorithm
825
-encrypt.cipher-mode Name of encryption cipher mode
826
-encrypt.ivgen-alg Name of IV generator algorithm
827
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
828
-encrypt.hash-alg Name of encryption hash algorithm
829
-encrypt.iter-time Time to spend in PBKDF in milliseconds
830
-cluster_size qcow2 cluster size
831
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
832
-lazy_refcounts Postpone refcount updates
833
-refcount_bits Width of a reference count entry in bits
834
+ backing_file=<str> - File name of a base image
835
+ backing_fmt=<str> - Image format of the base image
836
+ cluster_size=<size> - qcow2 cluster size
837
+ compat=<str> - Compatibility level (0.10 or 1.1)
838
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
839
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
840
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
841
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
842
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
843
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
844
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
845
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
846
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
847
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
848
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
849
+ refcount_bits=<num> - Width of a reference count entry in bits
850
+ size=<size> - Virtual disk size
851
852
Testing: convert -o help
853
Supported options:
854
-size Virtual disk size
855
+ size=<size> - Virtual disk size
856
857
Testing: convert -O bochs -o help
858
qemu-img: Format driver 'bochs' does not support image creation
859
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
860
861
Testing: amend -f qcow2 -o help TEST_DIR/t.qcow2
862
Creation options for 'qcow2':
863
-size Virtual disk size
864
-compat Compatibility level (0.10 or 1.1)
865
-backing_file File name of a base image
866
-backing_fmt Image format of the base image
867
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
868
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
869
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
870
-encrypt.cipher-alg Name of encryption cipher algorithm
871
-encrypt.cipher-mode Name of encryption cipher mode
872
-encrypt.ivgen-alg Name of IV generator algorithm
873
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
874
-encrypt.hash-alg Name of encryption hash algorithm
875
-encrypt.iter-time Time to spend in PBKDF in milliseconds
876
-cluster_size qcow2 cluster size
877
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
878
-lazy_refcounts Postpone refcount updates
879
-refcount_bits Width of a reference count entry in bits
880
+ backing_file=<str> - File name of a base image
881
+ backing_fmt=<str> - Image format of the base image
882
+ cluster_size=<size> - qcow2 cluster size
883
+ compat=<str> - Compatibility level (0.10 or 1.1)
884
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
885
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
886
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
887
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
888
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
889
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
890
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
891
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
892
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
893
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
894
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
895
+ refcount_bits=<num> - Width of a reference count entry in bits
896
+ size=<size> - Virtual disk size
897
898
Note that not all of these options may be amendable.
899
900
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
901
Creation options for 'qcow2':
902
-size Virtual disk size
903
-compat Compatibility level (0.10 or 1.1)
904
-backing_file File name of a base image
905
-backing_fmt Image format of the base image
906
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
907
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
908
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
909
-encrypt.cipher-alg Name of encryption cipher algorithm
910
-encrypt.cipher-mode Name of encryption cipher mode
911
-encrypt.ivgen-alg Name of IV generator algorithm
912
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
913
-encrypt.hash-alg Name of encryption hash algorithm
914
-encrypt.iter-time Time to spend in PBKDF in milliseconds
915
-cluster_size qcow2 cluster size
916
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
917
-lazy_refcounts Postpone refcount updates
918
-refcount_bits Width of a reference count entry in bits
919
+ backing_file=<str> - File name of a base image
920
+ backing_fmt=<str> - Image format of the base image
921
+ cluster_size=<size> - qcow2 cluster size
922
+ compat=<str> - Compatibility level (0.10 or 1.1)
923
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
924
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
925
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
926
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
927
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
928
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
929
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
930
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
931
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
932
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
933
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
934
+ refcount_bits=<num> - Width of a reference count entry in bits
935
+ size=<size> - Virtual disk size
936
937
Note that not all of these options may be amendable.
938
939
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
940
Creation options for 'qcow2':
941
-size Virtual disk size
942
-compat Compatibility level (0.10 or 1.1)
943
-backing_file File name of a base image
944
-backing_fmt Image format of the base image
945
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
946
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
947
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
948
-encrypt.cipher-alg Name of encryption cipher algorithm
949
-encrypt.cipher-mode Name of encryption cipher mode
950
-encrypt.ivgen-alg Name of IV generator algorithm
951
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
952
-encrypt.hash-alg Name of encryption hash algorithm
953
-encrypt.iter-time Time to spend in PBKDF in milliseconds
954
-cluster_size qcow2 cluster size
955
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
956
-lazy_refcounts Postpone refcount updates
957
-refcount_bits Width of a reference count entry in bits
958
+ backing_file=<str> - File name of a base image
959
+ backing_fmt=<str> - Image format of the base image
960
+ cluster_size=<size> - qcow2 cluster size
961
+ compat=<str> - Compatibility level (0.10 or 1.1)
962
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
963
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
964
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
965
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
966
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
967
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
968
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
969
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
970
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
971
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
972
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
973
+ refcount_bits=<num> - Width of a reference count entry in bits
974
+ size=<size> - Virtual disk size
975
976
Note that not all of these options may be amendable.
977
978
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
979
Creation options for 'qcow2':
980
-size Virtual disk size
981
-compat Compatibility level (0.10 or 1.1)
982
-backing_file File name of a base image
983
-backing_fmt Image format of the base image
984
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
985
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
986
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
987
-encrypt.cipher-alg Name of encryption cipher algorithm
988
-encrypt.cipher-mode Name of encryption cipher mode
989
-encrypt.ivgen-alg Name of IV generator algorithm
990
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
991
-encrypt.hash-alg Name of encryption hash algorithm
992
-encrypt.iter-time Time to spend in PBKDF in milliseconds
993
-cluster_size qcow2 cluster size
994
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
995
-lazy_refcounts Postpone refcount updates
996
-refcount_bits Width of a reference count entry in bits
997
+ backing_file=<str> - File name of a base image
998
+ backing_fmt=<str> - Image format of the base image
999
+ cluster_size=<size> - qcow2 cluster size
1000
+ compat=<str> - Compatibility level (0.10 or 1.1)
1001
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1002
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1003
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1004
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1005
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1006
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1007
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1008
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1009
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1010
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1011
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1012
+ refcount_bits=<num> - Width of a reference count entry in bits
1013
+ size=<size> - Virtual disk size
1014
1015
Note that not all of these options may be amendable.
1016
1017
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
1018
Creation options for 'qcow2':
1019
-size Virtual disk size
1020
-compat Compatibility level (0.10 or 1.1)
1021
-backing_file File name of a base image
1022
-backing_fmt Image format of the base image
1023
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1024
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1025
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1026
-encrypt.cipher-alg Name of encryption cipher algorithm
1027
-encrypt.cipher-mode Name of encryption cipher mode
1028
-encrypt.ivgen-alg Name of IV generator algorithm
1029
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1030
-encrypt.hash-alg Name of encryption hash algorithm
1031
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1032
-cluster_size qcow2 cluster size
1033
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1034
-lazy_refcounts Postpone refcount updates
1035
-refcount_bits Width of a reference count entry in bits
1036
+ backing_file=<str> - File name of a base image
1037
+ backing_fmt=<str> - Image format of the base image
1038
+ cluster_size=<size> - qcow2 cluster size
1039
+ compat=<str> - Compatibility level (0.10 or 1.1)
1040
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1041
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1042
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1043
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1044
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1045
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1046
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1047
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1048
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1049
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1050
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1051
+ refcount_bits=<num> - Width of a reference count entry in bits
1052
+ size=<size> - Virtual disk size
1053
1054
Note that not all of these options may be amendable.
1055
1056
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
1057
Creation options for 'qcow2':
1058
-size Virtual disk size
1059
-compat Compatibility level (0.10 or 1.1)
1060
-backing_file File name of a base image
1061
-backing_fmt Image format of the base image
1062
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1063
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1064
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1065
-encrypt.cipher-alg Name of encryption cipher algorithm
1066
-encrypt.cipher-mode Name of encryption cipher mode
1067
-encrypt.ivgen-alg Name of IV generator algorithm
1068
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1069
-encrypt.hash-alg Name of encryption hash algorithm
1070
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1071
-cluster_size qcow2 cluster size
1072
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1073
-lazy_refcounts Postpone refcount updates
1074
-refcount_bits Width of a reference count entry in bits
1075
+ backing_file=<str> - File name of a base image
1076
+ backing_fmt=<str> - Image format of the base image
1077
+ cluster_size=<size> - qcow2 cluster size
1078
+ compat=<str> - Compatibility level (0.10 or 1.1)
1079
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1080
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1081
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1082
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1083
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1084
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1085
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1086
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1087
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1088
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1089
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1090
+ refcount_bits=<num> - Width of a reference count entry in bits
1091
+ size=<size> - Virtual disk size
1092
1093
Note that not all of these options may be amendable.
1094
1095
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
1096
Creation options for 'qcow2':
1097
-size Virtual disk size
1098
-compat Compatibility level (0.10 or 1.1)
1099
-backing_file File name of a base image
1100
-backing_fmt Image format of the base image
1101
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1102
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1103
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1104
-encrypt.cipher-alg Name of encryption cipher algorithm
1105
-encrypt.cipher-mode Name of encryption cipher mode
1106
-encrypt.ivgen-alg Name of IV generator algorithm
1107
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1108
-encrypt.hash-alg Name of encryption hash algorithm
1109
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1110
-cluster_size qcow2 cluster size
1111
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1112
-lazy_refcounts Postpone refcount updates
1113
-refcount_bits Width of a reference count entry in bits
1114
+ backing_file=<str> - File name of a base image
1115
+ backing_fmt=<str> - Image format of the base image
1116
+ cluster_size=<size> - qcow2 cluster size
1117
+ compat=<str> - Compatibility level (0.10 or 1.1)
1118
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1119
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1120
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1121
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1122
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1123
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1124
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1125
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1126
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1127
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1128
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1129
+ refcount_bits=<num> - Width of a reference count entry in bits
1130
+ size=<size> - Virtual disk size
1131
1132
Note that not all of these options may be amendable.
1133
1134
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
1135
Creation options for 'qcow2':
1136
-size Virtual disk size
1137
-compat Compatibility level (0.10 or 1.1)
1138
-backing_file File name of a base image
1139
-backing_fmt Image format of the base image
1140
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1141
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1142
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1143
-encrypt.cipher-alg Name of encryption cipher algorithm
1144
-encrypt.cipher-mode Name of encryption cipher mode
1145
-encrypt.ivgen-alg Name of IV generator algorithm
1146
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1147
-encrypt.hash-alg Name of encryption hash algorithm
1148
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1149
-cluster_size qcow2 cluster size
1150
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1151
-lazy_refcounts Postpone refcount updates
1152
-refcount_bits Width of a reference count entry in bits
1153
+ backing_file=<str> - File name of a base image
1154
+ backing_fmt=<str> - Image format of the base image
1155
+ cluster_size=<size> - qcow2 cluster size
1156
+ compat=<str> - Compatibility level (0.10 or 1.1)
1157
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1158
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1159
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1160
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1161
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1162
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1163
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1164
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1165
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1166
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1167
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1168
+ refcount_bits=<num> - Width of a reference count entry in bits
1169
+ size=<size> - Virtual disk size
1170
1171
Note that not all of these options may be amendable.
1172
1173
@@ -XXX,XX +XXX,XX @@ qemu-img: Invalid option list: ,,
1174
1175
Testing: amend -f qcow2 -o help
1176
Creation options for 'qcow2':
1177
-size Virtual disk size
1178
-compat Compatibility level (0.10 or 1.1)
1179
-backing_file File name of a base image
1180
-backing_fmt Image format of the base image
1181
-encryption Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1182
-encrypt.format Encrypt the image, format choices: 'aes', 'luks'
1183
-encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
1184
-encrypt.cipher-alg Name of encryption cipher algorithm
1185
-encrypt.cipher-mode Name of encryption cipher mode
1186
-encrypt.ivgen-alg Name of IV generator algorithm
1187
-encrypt.ivgen-hash-alg Name of IV generator hash algorithm
1188
-encrypt.hash-alg Name of encryption hash algorithm
1189
-encrypt.iter-time Time to spend in PBKDF in milliseconds
1190
-cluster_size qcow2 cluster size
1191
-preallocation Preallocation mode (allowed values: off, metadata, falloc, full)
1192
-lazy_refcounts Postpone refcount updates
1193
-refcount_bits Width of a reference count entry in bits
1194
+ backing_file=<str> - File name of a base image
1195
+ backing_fmt=<str> - Image format of the base image
1196
+ cluster_size=<size> - qcow2 cluster size
1197
+ compat=<str> - Compatibility level (0.10 or 1.1)
1198
+ encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
1199
+ encrypt.cipher-mode=<str> - Name of encryption cipher mode
1200
+ encrypt.format=<str> - Encrypt the image, format choices: 'aes', 'luks'
1201
+ encrypt.hash-alg=<str> - Name of encryption hash algorithm
1202
+ encrypt.iter-time=<num> - Time to spend in PBKDF in milliseconds
1203
+ encrypt.ivgen-alg=<str> - Name of IV generator algorithm
1204
+ encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
1205
+ encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
1206
+ encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
1207
+ lazy_refcounts=<bool (on/off)> - Postpone refcount updates
1208
+ preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
1209
+ refcount_bits=<num> - Width of a reference count entry in bits
1210
+ size=<size> - Virtual disk size
1211
1212
Note that not all of these options may be amendable.
1213
1214
Testing: convert -o help
1215
Supported options:
1216
-size Virtual disk size
1217
+ size=<size> - Virtual disk size
1218
1219
Testing: amend -f bochs -o help
1220
qemu-img: Format driver 'bochs' does not support option amendment
1221
--
180
--
1222
2.19.1
181
2.20.1
1223
182
1224
183
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Make bdrv_get_full_backing_filename() return an allocated string instead
4
of placing the result in a caller-provided buffer.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Message-id: 20190201192935.18394-12-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
include/block/block.h | 3 +--
12
block.c | 48 +++++++++++++++----------------------------
13
block/qapi.c | 12 ++---------
14
3 files changed, 20 insertions(+), 43 deletions(-)
15
16
diff --git a/include/block/block.h b/include/block/block.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
19
+++ b/include/block/block.h
20
@@ -XXX,XX +XXX,XX @@ void bdrv_round_to_clusters(BlockDriverState *bs,
21
22
void bdrv_get_backing_filename(BlockDriverState *bs,
23
char *filename, int filename_size);
24
-void bdrv_get_full_backing_filename(BlockDriverState *bs,
25
- char *dest, size_t sz, Error **errp);
26
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
27
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
28
const char *backing,
29
Error **errp);
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
35
}
36
}
37
38
-void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,
39
- Error **errp)
40
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
41
{
42
char *backed;
43
- char *full_name;
44
- Error *local_error = NULL;
45
46
bdrv_refresh_filename(bs);
47
48
backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
49
-
50
- full_name = bdrv_get_full_backing_filename_from_filename(backed,
51
- bs->backing_file,
52
- &local_error);
53
- if (full_name) {
54
- pstrcpy(dest, sz, full_name);
55
- g_free(full_name);
56
- } else if (local_error) {
57
- error_propagate(errp, local_error);
58
- } else if (sz > 0) {
59
- *dest = '\0';
60
- }
61
+ return bdrv_get_full_backing_filename_from_filename(backed,
62
+ bs->backing_file,
63
+ errp);
64
}
65
66
void bdrv_register(BlockDriver *bdrv)
67
@@ -XXX,XX +XXX,XX @@ out:
68
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
69
const char *bdref_key, Error **errp)
70
{
71
- char *backing_filename = g_malloc0(PATH_MAX);
72
+ char *backing_filename = NULL;
73
char *bdref_key_dot;
74
const char *reference = NULL;
75
int ret = 0;
76
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
77
*/
78
reference = qdict_get_try_str(parent_options, bdref_key);
79
if (reference || qdict_haskey(options, "file.filename")) {
80
- backing_filename[0] = '\0';
81
+ /* keep backing_filename NULL */
82
} else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) {
83
qobject_unref(options);
84
goto free_exit;
85
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
86
implicit_backing = !strcmp(bs->auto_backing_file, bs->backing_file);
87
}
88
89
- bdrv_get_full_backing_filename(bs, backing_filename, PATH_MAX,
90
- &local_err);
91
+ backing_filename = bdrv_get_full_backing_filename(bs, &local_err);
92
if (local_err) {
93
ret = -EINVAL;
94
error_propagate(errp, local_err);
95
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
96
qdict_put_str(options, "driver", bs->backing_format);
97
}
98
99
- backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
100
- reference, options, 0, bs, &child_backing,
101
- errp);
102
+ backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
103
+ &child_backing, errp);
104
if (!backing_hd) {
105
bs->open_flags |= BDRV_O_NO_BACKING;
106
error_prepend(errp, "Could not open backing file: ");
107
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
108
int is_protocol = 0;
109
BlockDriverState *curr_bs = NULL;
110
BlockDriverState *retval = NULL;
111
- Error *local_error = NULL;
112
113
if (!bs || !bs->drv || !backing_file) {
114
return NULL;
115
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
116
/* If either of the filename paths is actually a protocol, then
117
* compare unmodified paths; otherwise make paths relative */
118
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
119
+ char *backing_file_full_ret;
120
+
121
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
122
retval = curr_bs->backing->bs;
123
break;
124
}
125
/* Also check against the full backing filename for the image */
126
- bdrv_get_full_backing_filename(curr_bs, backing_file_full, PATH_MAX,
127
- &local_error);
128
- if (local_error == NULL) {
129
- if (strcmp(backing_file, backing_file_full) == 0) {
130
+ backing_file_full_ret = bdrv_get_full_backing_filename(curr_bs,
131
+ NULL);
132
+ if (backing_file_full_ret) {
133
+ bool equal = strcmp(backing_file, backing_file_full_ret) == 0;
134
+ g_free(backing_file_full_ret);
135
+ if (equal) {
136
retval = curr_bs->backing->bs;
137
break;
138
}
139
- } else {
140
- error_free(local_error);
141
- local_error = NULL;
142
}
143
} else {
144
/* If not an absolute filename path, make it relative to the current
145
diff --git a/block/qapi.c b/block/qapi.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/block/qapi.c
148
+++ b/block/qapi.c
149
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
150
151
backing_filename = bs->backing_file;
152
if (backing_filename[0] != '\0') {
153
- char *backing_filename2 = g_malloc0(PATH_MAX);
154
+ char *backing_filename2;
155
info->backing_filename = g_strdup(backing_filename);
156
info->has_backing_filename = true;
157
- bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
158
- if (err) {
159
- /* Can't reconstruct the full backing filename, so we must omit
160
- * this field and apply a Best Effort to this query. */
161
- g_free(backing_filename2);
162
- backing_filename2 = NULL;
163
- error_free(err);
164
- err = NULL;
165
- }
166
+ backing_filename2 = bdrv_get_full_backing_filename(bs, NULL);
167
168
/* Always report the full_backing_filename if present, even if it's the
169
* same as backing_filename. That they are same is useful info. */
170
--
171
2.20.1
172
173
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
This is a general function for making a filename that is relative to a
4
certain BDS absolute.
5
6
It calls bdrv_get_full_backing_filename_from_filename() for now, but
7
that will be changed in a follow-up patch.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-13-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block.c | 27 ++++++++++++++++++++-------
15
1 file changed, 20 insertions(+), 7 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
22
}
23
}
24
25
-char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
26
+/*
27
+ * If @filename is empty or NULL, this function returns NULL without
28
+ * setting @errp. In all other cases, NULL will only be returned with
29
+ * @errp set.
30
+ */
31
+static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
32
+ const char *filename, Error **errp)
33
{
34
- char *backed;
35
+ char *bs_filename;
36
37
- bdrv_refresh_filename(bs);
38
+ bdrv_refresh_filename(relative_to);
39
+
40
+ bs_filename = relative_to->exact_filename[0]
41
+ ? relative_to->exact_filename
42
+ : relative_to->filename;
43
44
- backed = bs->exact_filename[0] ? bs->exact_filename : bs->filename;
45
- return bdrv_get_full_backing_filename_from_filename(backed,
46
- bs->backing_file,
47
- errp);
48
+ return bdrv_get_full_backing_filename_from_filename(bs_filename,
49
+ filename ?: "", errp);
50
+}
51
+
52
+char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
53
+{
54
+ return bdrv_make_absolute_filename(bs, bs->backing_file, errp);
55
}
56
57
void bdrv_register(BlockDriver *bdrv)
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
bdrv_find_backing_image() should use bdrv_get_full_backing_filename() or
4
bdrv_make_absolute_filename() instead of trying to do what those
5
functions do by itself.
6
7
path_combine_deprecated() can now be dropped, so let's do that.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-14-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block.c | 33 ++++++++++-----------------------
15
1 file changed, 10 insertions(+), 23 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ char *path_combine(const char *base_path, const char *filename)
22
return result;
23
}
24
25
-static void path_combine_deprecated(char *dest, int dest_size,
26
- const char *base_path,
27
- const char *filename)
28
-{
29
- char *combined = path_combine(base_path, filename);
30
- pstrcpy(dest, dest_size, combined);
31
- g_free(combined);
32
-}
33
-
34
/*
35
* Helper function for bdrv_parse_filename() implementations to remove optional
36
* protocol prefixes (especially "file:") from a filename and for putting the
37
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
38
39
filename_full = g_malloc(PATH_MAX);
40
backing_file_full = g_malloc(PATH_MAX);
41
- filename_tmp = g_malloc(PATH_MAX);
42
43
is_protocol = path_has_protocol(backing_file);
44
45
- /* This will recursively refresh everything in the backing chain */
46
- bdrv_refresh_filename(bs);
47
-
48
for (curr_bs = bs; curr_bs->backing; curr_bs = curr_bs->backing->bs) {
49
50
/* If either of the filename paths is actually a protocol, then
51
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
52
} else {
53
/* If not an absolute filename path, make it relative to the current
54
* image's filename path */
55
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
56
- backing_file);
57
-
58
- /* We are going to compare absolute pathnames */
59
- if (!realpath(filename_tmp, filename_full)) {
60
+ filename_tmp = bdrv_make_absolute_filename(curr_bs, backing_file,
61
+ NULL);
62
+ /* We are going to compare canonicalized absolute pathnames */
63
+ if (!filename_tmp || !realpath(filename_tmp, filename_full)) {
64
+ g_free(filename_tmp);
65
continue;
66
}
67
+ g_free(filename_tmp);
68
69
/* We need to make sure the backing filename we are comparing against
70
* is relative to the current image filename (or absolute) */
71
- path_combine_deprecated(filename_tmp, PATH_MAX, curr_bs->filename,
72
- curr_bs->backing_file);
73
-
74
- if (!realpath(filename_tmp, backing_file_full)) {
75
+ filename_tmp = bdrv_get_full_backing_filename(curr_bs, NULL);
76
+ if (!filename_tmp || !realpath(filename_tmp, backing_file_full)) {
77
+ g_free(filename_tmp);
78
continue;
79
}
80
+ g_free(filename_tmp);
81
82
if (strcmp(backing_file_full, filename_full) == 0) {
83
retval = curr_bs->backing->bs;
84
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
85
86
g_free(filename_full);
87
g_free(backing_file_full);
88
- g_free(filename_tmp);
89
return retval;
90
}
91
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
1
Some block drivers have traditionally changed their node to read-only
1
From: Max Reitz <mreitz@redhat.com>
2
mode without asking the user. This behaviour has been marked deprecated
3
since 2.11, expecting users to provide an explicit read-only=on option.
4
2
5
Now that we have auto-read-only=on, enable these drivers to make use of
3
This function may be implemented by block drivers to derive a directory
6
the option.
4
name from a BDS. Concatenating this g_free()-able string with a relative
5
filename must result in a valid (not necessarily existing) filename, so
6
this is a function that should generally be not implemented by format
7
drivers, because this is protocol-specific.
7
8
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
9
If a BDS's driver does not implement this function, bdrv_dirname() will
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
10
fall through to the BDS's file if it exists. If it does not, the
10
more convenient for drivers to use.
11
exact_filename field will be used to generate a directory name.
11
12
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Message-id: 20190201192935.18394-15-mreitz@redhat.com
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
17
---
15
include/block/block.h | 3 ++-
18
include/block/block.h | 1 +
16
block.c | 42 +++++++++++++++++++++++++++---------------
19
include/block/block_int.h | 7 +++++++
17
block/bochs.c | 17 ++++++-----------
20
block.c | 27 +++++++++++++++++++++++++++
18
block/cloop.c | 16 +++++-----------
21
3 files changed, 35 insertions(+)
19
block/dmg.c | 16 +++++-----------
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
23
22
24
diff --git a/include/block/block.h b/include/block/block.h
23
diff --git a/include/block/block.h b/include/block/block.h
25
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
26
--- a/include/block/block.h
25
--- a/include/block/block.h
27
+++ b/include/block/block.h
26
+++ b/include/block/block.h
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
27
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp);
29
bool bdrv_is_read_only(BlockDriverState *bs);
28
char *bdrv_get_full_backing_filename_from_filename(const char *backed,
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
29
const char *backing,
31
bool ignore_allow_rdw, Error **errp);
30
Error **errp);
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
31
+char *bdrv_dirname(BlockDriverState *bs, Error **errp);
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
32
34
+ Error **errp);
33
int path_has_protocol(const char *path);
35
bool bdrv_is_writable(BlockDriverState *bs);
34
int path_is_absolute(const char *path);
36
bool bdrv_is_sg(BlockDriverState *bs);
35
diff --git a/include/block/block_int.h b/include/block/block_int.h
37
bool bdrv_is_inserted(BlockDriverState *bs);
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/block/block_int.h
38
+++ b/include/block/block_int.h
39
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
40
41
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
42
43
+ /*
44
+ * Returns an allocated string which is the directory name of this BDS: It
45
+ * will be used to make relative filenames absolute by prepending this
46
+ * function's return value to them.
47
+ */
48
+ char *(*bdrv_dirname)(BlockDriverState *bs, Error **errp);
49
+
50
/* aio */
51
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
52
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
38
diff --git a/block.c b/block.c
53
diff --git a/block.c b/block.c
39
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
40
--- a/block.c
55
--- a/block.c
41
+++ b/block.c
56
+++ b/block.c
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
57
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
43
return 0;
58
}
44
}
59
}
45
60
46
-/* TODO Remove (deprecated since 2.11)
61
+char *bdrv_dirname(BlockDriverState *bs, Error **errp)
47
- * Block drivers are not supposed to automatically change bs->read_only.
62
+{
48
- * Instead, they should just check whether they can provide what the user
63
+ BlockDriver *drv = bs->drv;
49
- * explicitly requested and error out if read-write is requested, but they can
50
- * only provide read-only access. */
51
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
52
+/*
53
+ * Called by a driver that can only provide a read-only image.
54
+ *
55
+ * Returns 0 if the node is already read-only or it could switch the node to
56
+ * read-only because BDRV_O_AUTO_RDONLY is set.
57
+ *
58
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
59
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
60
+ * is not NULL, it is used as the error message for the Error object.
61
+ */
62
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
63
+ Error **errp)
64
{
65
int ret = 0;
66
67
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
68
- if (ret < 0) {
69
- return ret;
70
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
71
+ return 0;
72
+ }
73
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
74
+ goto fail;
75
}
76
77
- bs->read_only = read_only;
78
-
79
- if (read_only) {
80
- bs->open_flags &= ~BDRV_O_RDWR;
81
- } else {
82
- bs->open_flags |= BDRV_O_RDWR;
83
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
84
+ if (ret < 0) {
85
+ goto fail;
86
}
87
88
+ bs->read_only = true;
89
+ bs->open_flags &= ~BDRV_O_RDWR;
90
+
64
+
91
return 0;
65
+ if (!drv) {
92
+
66
+ error_setg(errp, "Node '%s' is ejected", bs->node_name);
93
+fail:
67
+ return NULL;
94
+ error_setg(errp, "%s", errmsg ?: "Image is read-only");
95
+ return -EACCES;
96
}
97
98
void bdrv_get_full_backing_filename_from_filename(const char *backed,
99
diff --git a/block/bochs.c b/block/bochs.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/bochs.c
102
+++ b/block/bochs.c
103
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
104
struct bochs_header bochs;
105
int ret;
106
107
+ /* No write support yet */
108
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
109
+ if (ret < 0) {
110
+ return ret;
111
+ }
68
+ }
112
+
69
+
113
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
70
+ if (drv->bdrv_dirname) {
114
false, errp);
71
+ return drv->bdrv_dirname(bs, errp);
115
if (!bs->file) {
116
return -EINVAL;
117
}
118
119
- if (!bdrv_is_read_only(bs)) {
120
- error_report("Opening bochs images without an explicit read-only=on "
121
- "option is deprecated. Future versions will refuse to "
122
- "open the image instead of automatically marking the "
123
- "image read-only.");
124
- ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
125
- if (ret < 0) {
126
- return ret;
127
- }
128
- }
129
-
130
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
131
if (ret < 0) {
132
return ret;
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 int cloop_open(BlockDriverState *bs, QDict *options, int flags,
138
uint32_t offsets_size, max_compressed_block_size = 1, i;
139
int ret;
140
141
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
142
+ if (ret < 0) {
143
+ return ret;
144
+ }
72
+ }
145
+
73
+
146
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
74
+ if (bs->file) {
147
false, errp);
75
+ return bdrv_dirname(bs->file->bs, errp);
148
if (!bs->file) {
149
return -EINVAL;
150
}
151
152
- if (!bdrv_is_read_only(bs)) {
153
- error_report("Opening cloop images without an explicit read-only=on "
154
- "option is deprecated. Future versions will refuse to "
155
- "open the image instead of automatically marking the "
156
- "image read-only.");
157
- ret = bdrv_set_read_only(bs, true, errp);
158
- if (ret < 0) {
159
- return ret;
160
- }
161
- }
162
-
163
/* read header */
164
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
165
if (ret < 0) {
166
diff --git a/block/dmg.c b/block/dmg.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/dmg.c
169
+++ b/block/dmg.c
170
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
171
int64_t offset;
172
int ret;
173
174
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
175
+ if (ret < 0) {
176
+ return ret;
177
+ }
76
+ }
178
+
77
+
179
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
78
+ bdrv_refresh_filename(bs);
180
false, errp);
79
+ if (bs->exact_filename[0] != '\0') {
181
if (!bs->file) {
80
+ return path_combine(bs->exact_filename, "");
182
return -EINVAL;
81
+ }
183
}
82
+
184
83
+ error_setg(errp, "Cannot generate a base directory for %s nodes",
185
- if (!bdrv_is_read_only(bs)) {
84
+ drv->format_name);
186
- error_report("Opening dmg images without an explicit read-only=on "
85
+ return NULL;
187
- "option is deprecated. Future versions will refuse to "
86
+}
188
- "open the image instead of automatically marking the "
87
+
189
- "image read-only.");
88
/*
190
- ret = bdrv_set_read_only(bs, true, errp);
89
* Hot add/remove a BDS's child. So the user can take a child offline when
191
- if (ret < 0) {
90
* it is broken and take a new child online
192
- return ret;
193
- }
194
- }
195
-
196
block_module_load_one("dmg-bz2");
197
198
s->n_chunks = 0;
199
diff --git a/block/rbd.c b/block/rbd.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/rbd.c
202
+++ b/block/rbd.c
203
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
204
/* If we are using an rbd snapshot, we must be r/o, otherwise
205
* leave as-is */
206
if (s->snap != NULL) {
207
- if (!bdrv_is_read_only(bs)) {
208
- error_report("Opening rbd snapshots without an explicit "
209
- "read-only=on option is deprecated. Future versions "
210
- "will refuse to open the image instead of "
211
- "automatically marking the image read-only.");
212
- r = bdrv_set_read_only(bs, true, &local_err);
213
- if (r < 0) {
214
- rbd_close(s->image);
215
- error_propagate(errp, local_err);
216
- goto failed_open;
217
- }
218
+ r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
219
+ if (r < 0) {
220
+ rbd_close(s->image);
221
+ goto failed_open;
222
}
223
}
224
225
diff --git a/block/vvfat.c b/block/vvfat.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/block/vvfat.c
228
+++ b/block/vvfat.c
229
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
230
"Unable to set VVFAT to 'rw' when drive is read-only");
231
goto fail;
232
}
233
- } else if (!bdrv_is_read_only(bs)) {
234
- error_report("Opening non-rw vvfat images without an explicit "
235
- "read-only=on option is deprecated. Future versions "
236
- "will refuse to open the image instead of "
237
- "automatically marking the image read-only.");
238
- /* read only is the default for safety */
239
- ret = bdrv_set_read_only(bs, true, &local_err);
240
+ } else {
241
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
242
if (ret < 0) {
243
- error_propagate(errp, local_err);
244
goto fail;
245
}
246
}
247
--
91
--
248
2.19.1
92
2.20.1
249
93
250
94
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
blkverify's BDSs have a file BDS, but we do not want this to be
4
preferred over the raw node. There is no way to decide between the two
5
(and not really a reason to, either), so just return NULL in blkverify's
6
implementation of bdrv_dirname().
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-16-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/blkverify.c | 10 ++++++++++
15
1 file changed, 10 insertions(+)
16
17
diff --git a/block/blkverify.c b/block/blkverify.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/blkverify.c
20
+++ b/block/blkverify.c
21
@@ -XXX,XX +XXX,XX @@ static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
22
}
23
}
24
25
+static char *blkverify_dirname(BlockDriverState *bs, Error **errp)
26
+{
27
+ /* In general, there are two BDSs with different dirnames below this one;
28
+ * so there is no unique dirname we could return (unless both are equal by
29
+ * chance). Therefore, to be consistent, just always return NULL. */
30
+ error_setg(errp, "Cannot generate a base directory for blkverify nodes");
31
+ return NULL;
32
+}
33
+
34
static BlockDriver bdrv_blkverify = {
35
.format_name = "blkverify",
36
.protocol_name = "blkverify",
37
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkverify = {
38
.bdrv_child_perm = bdrv_filter_default_perms,
39
.bdrv_getlength = blkverify_getlength,
40
.bdrv_refresh_filename = blkverify_refresh_filename,
41
+ .bdrv_dirname = blkverify_dirname,
42
43
.bdrv_co_preadv = blkverify_co_preadv,
44
.bdrv_co_pwritev = blkverify_co_pwritev,
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
The blkverify mode of Quorum can only be enabled if the number of
3
While the common implementation for bdrv_dirname() should return NULL
4
children is exactly two and the value of vote-threshold is also two.
4
for quorum BDSs already (because they do not have a file node and their
5
exact_filename field should be empty), there is no reason not to make
6
that explicit.
5
7
6
If the user tries to enable it but the other settings are incorrect
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
then QEMU simply prints an error message to stderr and carries on
9
Reviewed-by: Eric Blake <eblake@redhat.com>
8
disabling the blkverify setting.
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
11
Message-id: 20190201192935.18394-17-mreitz@redhat.com
10
This patch makes quorum_open() fail and return an error in this case.
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reported-by: Markus Armbruster <armbru@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
block/quorum.c | 13 ++++++-------
14
block/quorum.c | 11 +++++++++++
17
1 file changed, 6 insertions(+), 7 deletions(-)
15
1 file changed, 11 insertions(+)
18
16
19
diff --git a/block/quorum.c b/block/quorum.c
17
diff --git a/block/quorum.c b/block/quorum.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/block/quorum.c
19
--- a/block/quorum.c
22
+++ b/block/quorum.c
20
+++ b/block/quorum.c
23
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
21
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
24
s->read_pattern = ret;
22
bs->full_open_options = opts;
25
23
}
26
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
24
27
- /* is the driver in blkverify mode */
25
+static char *quorum_dirname(BlockDriverState *bs, Error **errp)
28
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
26
+{
29
- s->num_children == 2 && s->threshold == 2) {
27
+ /* In general, there are multiple BDSs with different dirnames below this
30
- s->is_blkverify = true;
28
+ * one; so there is no unique dirname we could return (unless all are equal
31
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
29
+ * by chance, or there is only one). Therefore, to be consistent, just
32
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
30
+ * always return NULL. */
33
- "and using two files with vote_threshold=2\n");
31
+ error_setg(errp, "Cannot generate a base directory for quorum nodes");
34
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
32
+ return NULL;
35
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
33
+}
36
+ error_setg(&local_err, "blkverify=on can only be set if there are "
34
+
37
+ "exactly two files and vote-threshold is 2");
35
static BlockDriver bdrv_quorum = {
38
+ ret = -EINVAL;
36
.format_name = "quorum",
39
+ goto exit;
37
40
}
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
41
39
.bdrv_open = quorum_open,
42
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
40
.bdrv_close = quorum_close,
41
.bdrv_refresh_filename = quorum_refresh_filename,
42
+ .bdrv_dirname = quorum_dirname,
43
44
.bdrv_co_flush_to_disk = quorum_co_flush,
45
43
--
46
--
44
2.19.1
47
2.20.1
45
48
46
49
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
The generic bdrv_dirname() implementation would be able to generate some
4
form of directory name for many NBD nodes, but it would be always wrong.
5
Therefore, we have to explicitly make it an error (until NBD has some
6
form of specification for export paths, if it ever will).
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20190201192935.18394-18-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/nbd.c | 13 +++++++++++++
15
1 file changed, 13 insertions(+)
16
17
diff --git a/block/nbd.c b/block/nbd.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/nbd.c
20
+++ b/block/nbd.c
21
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
22
bs->full_open_options = opts;
23
}
24
25
+static char *nbd_dirname(BlockDriverState *bs, Error **errp)
26
+{
27
+ /* The generic bdrv_dirname() implementation is able to work out some
28
+ * directory name for NBD nodes, but that would be wrong. So far there is no
29
+ * specification for how "export paths" would work, so NBD does not have
30
+ * directory names. */
31
+ error_setg(errp, "Cannot generate a base directory for NBD nodes");
32
+ return NULL;
33
+}
34
+
35
static BlockDriver bdrv_nbd = {
36
.format_name = "nbd",
37
.protocol_name = "nbd",
38
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
39
.bdrv_attach_aio_context = nbd_attach_aio_context,
40
.bdrv_refresh_filename = nbd_refresh_filename,
41
.bdrv_co_block_status = nbd_client_co_block_status,
42
+ .bdrv_dirname = nbd_dirname,
43
};
44
45
static BlockDriver bdrv_nbd_tcp = {
46
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
47
.bdrv_attach_aio_context = nbd_attach_aio_context,
48
.bdrv_refresh_filename = nbd_refresh_filename,
49
.bdrv_co_block_status = nbd_client_co_block_status,
50
+ .bdrv_dirname = nbd_dirname,
51
};
52
53
static BlockDriver bdrv_nbd_unix = {
54
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
55
.bdrv_attach_aio_context = nbd_attach_aio_context,
56
.bdrv_refresh_filename = nbd_refresh_filename,
57
.bdrv_co_block_status = nbd_client_co_block_status,
58
+ .bdrv_dirname = nbd_dirname,
59
};
60
61
static void bdrv_nbd_init(void)
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
While the basic idea is obvious and could be handled by the default
4
bdrv_dirname() implementation, we cannot generate a directory name if
5
the gid or uid are set, so we have to explicitly return NULL in those
6
cases.
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-19-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/nfs.c | 15 +++++++++++++++
14
1 file changed, 15 insertions(+)
15
16
diff --git a/block/nfs.c b/block/nfs.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/nfs.c
19
+++ b/block/nfs.c
20
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
21
bs->full_open_options = opts;
22
}
23
24
+static char *nfs_dirname(BlockDriverState *bs, Error **errp)
25
+{
26
+ NFSClient *client = bs->opaque;
27
+
28
+ if (client->uid || client->gid) {
29
+ bdrv_refresh_filename(bs);
30
+ error_setg(errp, "Cannot generate a base directory for NFS node '%s'",
31
+ bs->filename);
32
+ return NULL;
33
+ }
34
+
35
+ return g_strdup_printf("nfs://%s%s/", client->server->host, client->path);
36
+}
37
+
38
#ifdef LIBNFS_FEATURE_PAGECACHE
39
static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
40
Error **errp)
41
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
42
.bdrv_detach_aio_context = nfs_detach_aio_context,
43
.bdrv_attach_aio_context = nfs_attach_aio_context,
44
.bdrv_refresh_filename = nfs_refresh_filename,
45
+ .bdrv_dirname = nfs_dirname,
46
47
#ifdef LIBNFS_FEATURE_PAGECACHE
48
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
bdrv_get_full_backing_filename_from_filename() breaks down when it comes
4
to JSON filenames. Using bdrv_dirname() as the basis is better because
5
since we have BDS, we can descend through the BDS tree to the protocol
6
layer, which gives us a greater probability of finding a non-JSON name;
7
also, bdrv_dirname() is more correct as it allows block drivers to
8
override the generation of that directory name in a protocol-specific
9
way.
10
11
We still need to keep bdrv_get_full_backing_filename_from_filename(),
12
though, because it has valid callers which need it during image creation
13
when no BDS is available yet.
14
15
This makes a test case in qemu-iotest 110, which was supposed to fail,
16
work. That is actually good, but we need to change the reference output
17
(and the comment in 110) accordingly.
18
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
Reviewed-by: Alberto Garcia <berto@igalia.com>
21
Message-id: 20190201192935.18394-20-mreitz@redhat.com
22
Signed-off-by: Max Reitz <mreitz@redhat.com>
23
---
24
block.c | 20 +++++++++++++-------
25
tests/qemu-iotests/110 | 3 ++-
26
tests/qemu-iotests/110.out | 2 +-
27
3 files changed, 16 insertions(+), 9 deletions(-)
28
29
diff --git a/block.c b/block.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
32
+++ b/block.c
33
@@ -XXX,XX +XXX,XX @@ char *bdrv_get_full_backing_filename_from_filename(const char *backed,
34
static char *bdrv_make_absolute_filename(BlockDriverState *relative_to,
35
const char *filename, Error **errp)
36
{
37
- char *bs_filename;
38
+ char *dir, *full_name;
39
40
- bdrv_refresh_filename(relative_to);
41
+ if (!filename || filename[0] == '\0') {
42
+ return NULL;
43
+ } else if (path_has_protocol(filename) || path_is_absolute(filename)) {
44
+ return g_strdup(filename);
45
+ }
46
47
- bs_filename = relative_to->exact_filename[0]
48
- ? relative_to->exact_filename
49
- : relative_to->filename;
50
+ dir = bdrv_dirname(relative_to, errp);
51
+ if (!dir) {
52
+ return NULL;
53
+ }
54
55
- return bdrv_get_full_backing_filename_from_filename(bs_filename,
56
- filename ?: "", errp);
57
+ full_name = g_strconcat(dir, filename, NULL);
58
+ g_free(dir);
59
+ return full_name;
60
}
61
62
char *bdrv_get_full_backing_filename(BlockDriverState *bs, Error **errp)
63
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
64
index XXXXXXX..XXXXXXX 100755
65
--- a/tests/qemu-iotests/110
66
+++ b/tests/qemu-iotests/110
67
@@ -XXX,XX +XXX,XX @@ echo '=== Non-reconstructable filename ==='
68
echo
69
70
# Across blkdebug without a config file, you cannot reconstruct filenames, so
71
-# qemu is incapable of knowing the directory of the top image
72
+# qemu is incapable of knowing the directory of the top image from the filename
73
+# alone. However, using bdrv_dirname(), it should still work.
74
TEST_IMG="json:{
75
'driver': '$IMGFMT',
76
'file': {
77
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/110.out
80
+++ b/tests/qemu-iotests/110.out
81
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
82
image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
83
file format: IMGFMT
84
virtual size: 64M (67108864 bytes)
85
-backing file: t.IMGFMT.base (cannot determine actual path)
86
+backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
87
88
=== Backing name is always relative to the backed image ===
89
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
3
Test 110 tests relative backing filenames for complex BDS trees. Now
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
that the originally supposedly failing test passes, let us add a new
5
failing test: Quorum can never work automatically (without detecting
6
whether all child nodes have the same base directory, but that would be
7
rather inconsistent behavior).
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Message-id: 20190201192935.18394-21-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
---
13
---
6
tests/qemu-iotests/081 | 30 ++++++++++++++++++++++++++++++
14
tests/qemu-iotests/110 | 26 ++++++++++++++++++++++++++
7
tests/qemu-iotests/081.out | 16 ++++++++++++++++
15
tests/qemu-iotests/110.out | 7 +++++++
8
2 files changed, 46 insertions(+)
16
2 files changed, 33 insertions(+)
9
17
10
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
18
diff --git a/tests/qemu-iotests/110 b/tests/qemu-iotests/110
11
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100755
12
--- a/tests/qemu-iotests/081
20
--- a/tests/qemu-iotests/110
13
+++ b/tests/qemu-iotests/081
21
+++ b/tests/qemu-iotests/110
14
@@ -XXX,XX +XXX,XX @@ echo "== checking that quorum is broken =="
22
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
15
23
_cleanup()
16
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
24
{
25
    _cleanup_test_img
26
+ rm -f "$TEST_IMG.copy"
27
}
28
trap "_cleanup; exit \$status" 0 1 2 3 15
29
30
@@ -XXX,XX +XXX,XX @@ echo
31
# omit the image size; it should work anyway
32
_make_test_img -b "$TEST_IMG_REL.base"
17
33
18
+echo
34
+echo
19
+echo "== checking the blkverify mode with broken content =="
35
+echo '=== Nodes without a common directory ==='
36
+echo
20
+
37
+
21
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
38
+cp "$TEST_IMG" "$TEST_IMG.copy"
22
+quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
23
+quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
24
+quorum="$quorum,file.children.0.driver=raw"
25
+quorum="$quorum,file.children.1.driver=raw"
26
+
39
+
27
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
40
+# Should inform us that the actual path of the backing file cannot be determined
41
+TEST_IMG="json:{
42
+ 'driver': '$IMGFMT',
43
+ 'file': {
44
+ 'driver': 'quorum',
45
+ 'vote-threshold': 1,
46
+ 'children': [
47
+ {
48
+ 'driver': 'file',
49
+ 'filename': '$TEST_IMG'
50
+ },
51
+ {
52
+ 'driver': 'file',
53
+ 'filename': '$TEST_IMG.copy'
54
+ }
55
+ ]
56
+ }
57
+}" _img_info | _filter_img_info
28
+
58
+
29
+echo
59
30
+echo "== writing the same data to both files =="
60
# success, all done
61
echo '*** done'
62
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/110.out
65
+++ b/tests/qemu-iotests/110.out
66
@@ -XXX,XX +XXX,XX @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
67
=== Backing name is always relative to the backed image ===
68
69
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
31
+
70
+
32
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
71
+=== Nodes without a common directory ===
33
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
34
+
72
+
35
+echo
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}}
36
+echo "== checking the blkverify mode with valid content =="
74
+file format: IMGFMT
37
+
75
+virtual size: 64M (67108864 bytes)
38
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
76
+backing file: t.IMGFMT.base (cannot determine actual path)
39
+
40
+echo
41
+echo "== checking the blkverify mode with invalid settings =="
42
+
43
+quorum="$quorum,file.children.2.file.filename=$TEST_DIR/3.raw"
44
+quorum="$quorum,file.children.2.driver=raw"
45
+
46
+$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
47
+
48
# success, all done
49
echo "*** done"
50
rm -f $seq.full
51
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/081.out
54
+++ b/tests/qemu-iotests/081.out
55
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 0
56
57
== checking that quorum is broken ==
58
read failed: Input/output error
59
+
60
+== checking the blkverify mode with broken content ==
61
+quorum: offset=0 bytes=10485760 contents mismatch at offset 0
62
+
63
+== writing the same data to both files ==
64
+wrote 10485760/10485760 bytes at offset 0
65
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
+wrote 10485760/10485760 bytes at offset 0
67
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
68
+
69
+== checking the blkverify mode with valid content ==
70
+read 10485760/10485760 bytes at offset 0
71
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
72
+
73
+== checking the blkverify mode with invalid settings ==
74
+can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
75
*** done
77
*** done
76
--
78
--
77
2.19.1
79
2.20.1
78
80
79
81
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
3
This new field can be set by block drivers to list the runtime options
4
they accept that may influence the contents of the respective BDS. As of
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
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Message-id: 20190201192935.18394-22-mreitz@redhat.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
---
18
---
4
block/vpc.c | 2 ++
19
include/block/block_int.h | 7 +++++++
5
1 file changed, 2 insertions(+)
20
block/blkdebug.c | 16 ++++++++++++++++
21
block/blklogwrites.c | 8 ++++++++
22
block/crypto.c | 8 ++++++++
23
block/curl.c | 21 +++++++++++++++++++++
24
block/gluster.c | 19 +++++++++++++++++++
25
block/iscsi.c | 18 ++++++++++++++++++
26
block/nbd.c | 14 ++++++++++++++
27
block/nfs.c | 11 +++++++++++
28
block/null.c | 9 +++++++++
29
block/nvme.c | 8 ++++++++
30
block/qcow.c | 7 +++++++
31
block/qcow2.c | 7 +++++++
32
block/quorum.c | 11 +++++++++++
33
block/raw-format.c | 10 +++++++++-
34
block/rbd.c | 14 ++++++++++++++
35
block/replication.c | 8 ++++++++
36
block/sheepdog.c | 12 ++++++++++++
37
block/ssh.c | 12 ++++++++++++
38
block/throttle.c | 7 +++++++
39
block/vpc.c | 7 +++++++
40
block/vvfat.c | 12 ++++++++++++
41
block/vxhs.c | 11 +++++++++++
42
23 files changed, 256 insertions(+), 1 deletion(-)
6
43
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
50
void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
51
QLIST_ENTRY(BlockDriver) list;
52
+
53
+ /* Pointer to a NULL-terminated array of names of strong options
54
+ * that can be specified for bdrv_open(). A strong option is one
55
+ * that changes the data of a BDS.
56
+ * If this pointer is NULL, the array is considered empty.
57
+ * "filename" and "driver" are always considered strong. */
58
+ const char *const *strong_runtime_opts;
59
};
60
61
typedef struct BlockLimits {
62
diff --git a/block/blkdebug.c b/block/blkdebug.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/block/blkdebug.c
65
+++ b/block/blkdebug.c
66
@@ -XXX,XX +XXX,XX @@ static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
67
return 0;
68
}
69
70
+static const char *const blkdebug_strong_runtime_opts[] = {
71
+ "config",
72
+ "inject-error.",
73
+ "set-state.",
74
+ "align",
75
+ "max-transfer",
76
+ "opt-write-zero",
77
+ "max-write-zero",
78
+ "opt-discard",
79
+ "max-discard",
80
+
81
+ NULL
82
+};
83
+
84
static BlockDriver bdrv_blkdebug = {
85
.format_name = "blkdebug",
86
.protocol_name = "blkdebug",
87
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blkdebug = {
88
= blkdebug_debug_remove_breakpoint,
89
.bdrv_debug_resume = blkdebug_debug_resume,
90
.bdrv_debug_is_suspended = blkdebug_debug_is_suspended,
91
+
92
+ .strong_runtime_opts = blkdebug_strong_runtime_opts,
93
};
94
95
static void bdrv_blkdebug_init(void)
96
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blklogwrites.c
99
+++ b/block/blklogwrites.c
100
@@ -XXX,XX +XXX,XX @@ blk_log_writes_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
101
LOG_DISCARD_FLAG, false);
102
}
103
104
+static const char *const blk_log_writes_strong_runtime_opts[] = {
105
+ "log-append",
106
+ "log-sector-size",
107
+
108
+ NULL
109
+};
110
+
111
static BlockDriver bdrv_blk_log_writes = {
112
.format_name = "blklogwrites",
113
.instance_size = sizeof(BDRVBlkLogWritesState),
114
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
115
.bdrv_co_block_status = bdrv_co_block_status_from_file,
116
117
.is_filter = true,
118
+ .strong_runtime_opts = blk_log_writes_strong_runtime_opts,
119
};
120
121
static void bdrv_blk_log_writes_init(void)
122
diff --git a/block/crypto.c b/block/crypto.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/block/crypto.c
125
+++ b/block/crypto.c
126
@@ -XXX,XX +XXX,XX @@ block_crypto_get_specific_info_luks(BlockDriverState *bs, Error **errp)
127
return spec_info;
128
}
129
130
+static const char *const block_crypto_strong_runtime_opts[] = {
131
+ BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
132
+
133
+ NULL
134
+};
135
+
136
BlockDriver bdrv_crypto_luks = {
137
.format_name = "luks",
138
.instance_size = sizeof(BlockCrypto),
139
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
140
.bdrv_getlength = block_crypto_getlength,
141
.bdrv_get_info = block_crypto_get_info_luks,
142
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
143
+
144
+ .strong_runtime_opts = block_crypto_strong_runtime_opts,
145
};
146
147
static void block_crypto_init(void)
148
diff --git a/block/curl.c b/block/curl.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/curl.c
151
+++ b/block/curl.c
152
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
153
return s->len;
154
}
155
156
+static const char *const curl_strong_runtime_opts[] = {
157
+ CURL_BLOCK_OPT_URL,
158
+ CURL_BLOCK_OPT_SSLVERIFY,
159
+ CURL_BLOCK_OPT_COOKIE,
160
+ CURL_BLOCK_OPT_COOKIE_SECRET,
161
+ CURL_BLOCK_OPT_USERNAME,
162
+ CURL_BLOCK_OPT_PASSWORD_SECRET,
163
+ CURL_BLOCK_OPT_PROXY_USERNAME,
164
+ CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
165
+
166
+ NULL
167
+};
168
+
169
static BlockDriver bdrv_http = {
170
.format_name = "http",
171
.protocol_name = "http",
172
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
173
174
.bdrv_detach_aio_context = curl_detach_aio_context,
175
.bdrv_attach_aio_context = curl_attach_aio_context,
176
+
177
+ .strong_runtime_opts = curl_strong_runtime_opts,
178
};
179
180
static BlockDriver bdrv_https = {
181
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
182
183
.bdrv_detach_aio_context = curl_detach_aio_context,
184
.bdrv_attach_aio_context = curl_attach_aio_context,
185
+
186
+ .strong_runtime_opts = curl_strong_runtime_opts,
187
};
188
189
static BlockDriver bdrv_ftp = {
190
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
191
192
.bdrv_detach_aio_context = curl_detach_aio_context,
193
.bdrv_attach_aio_context = curl_attach_aio_context,
194
+
195
+ .strong_runtime_opts = curl_strong_runtime_opts,
196
};
197
198
static BlockDriver bdrv_ftps = {
199
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
200
201
.bdrv_detach_aio_context = curl_detach_aio_context,
202
.bdrv_attach_aio_context = curl_attach_aio_context,
203
+
204
+ .strong_runtime_opts = curl_strong_runtime_opts,
205
};
206
207
static void curl_block_init(void)
208
diff --git a/block/gluster.c b/block/gluster.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/gluster.c
211
+++ b/block/gluster.c
212
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
213
}
214
215
216
+static const char *const gluster_strong_open_opts[] = {
217
+ GLUSTER_OPT_VOLUME,
218
+ GLUSTER_OPT_PATH,
219
+ GLUSTER_OPT_TYPE,
220
+ GLUSTER_OPT_SERVER_PATTERN,
221
+ GLUSTER_OPT_HOST,
222
+ GLUSTER_OPT_PORT,
223
+ GLUSTER_OPT_TO,
224
+ GLUSTER_OPT_IPV4,
225
+ GLUSTER_OPT_IPV6,
226
+ GLUSTER_OPT_SOCKET,
227
+
228
+ NULL
229
+};
230
+
231
static BlockDriver bdrv_gluster = {
232
.format_name = "gluster",
233
.protocol_name = "gluster",
234
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
235
#endif
236
.bdrv_co_block_status = qemu_gluster_co_block_status,
237
.create_opts = &qemu_gluster_create_opts,
238
+ .strong_runtime_opts = gluster_strong_open_opts,
239
};
240
241
static BlockDriver bdrv_gluster_tcp = {
242
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
243
#endif
244
.bdrv_co_block_status = qemu_gluster_co_block_status,
245
.create_opts = &qemu_gluster_create_opts,
246
+ .strong_runtime_opts = gluster_strong_open_opts,
247
};
248
249
static BlockDriver bdrv_gluster_unix = {
250
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
251
#endif
252
.bdrv_co_block_status = qemu_gluster_co_block_status,
253
.create_opts = &qemu_gluster_create_opts,
254
+ .strong_runtime_opts = gluster_strong_open_opts,
255
};
256
257
/* rdma is deprecated (actually never supported for volfile fetch).
258
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
259
#endif
260
.bdrv_co_block_status = qemu_gluster_co_block_status,
261
.create_opts = &qemu_gluster_create_opts,
262
+ .strong_runtime_opts = gluster_strong_open_opts,
263
};
264
265
static void bdrv_gluster_init(void)
266
diff --git a/block/iscsi.c b/block/iscsi.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/block/iscsi.c
269
+++ b/block/iscsi.c
270
@@ -XXX,XX +XXX,XX @@ static QemuOptsList iscsi_create_opts = {
271
}
272
};
273
274
+static const char *const iscsi_strong_runtime_opts[] = {
275
+ "transport",
276
+ "portal",
277
+ "target",
278
+ "user",
279
+ "password",
280
+ "password-secret",
281
+ "lun",
282
+ "initiator-name",
283
+ "header-digest",
284
+
285
+ NULL
286
+};
287
+
288
static BlockDriver bdrv_iscsi = {
289
.format_name = "iscsi",
290
.protocol_name = "iscsi",
291
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
292
293
.bdrv_detach_aio_context = iscsi_detach_aio_context,
294
.bdrv_attach_aio_context = iscsi_attach_aio_context,
295
+
296
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
297
};
298
299
#if LIBISCSI_API_VERSION >= (20160603)
300
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
301
302
.bdrv_detach_aio_context = iscsi_detach_aio_context,
303
.bdrv_attach_aio_context = iscsi_attach_aio_context,
304
+
305
+ .strong_runtime_opts = iscsi_strong_runtime_opts,
306
};
307
#endif
308
309
diff --git a/block/nbd.c b/block/nbd.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/block/nbd.c
312
+++ b/block/nbd.c
313
@@ -XXX,XX +XXX,XX @@ static char *nbd_dirname(BlockDriverState *bs, Error **errp)
314
return NULL;
315
}
316
317
+static const char *const nbd_strong_runtime_opts[] = {
318
+ "path",
319
+ "host",
320
+ "port",
321
+ "export",
322
+ "tls-creds",
323
+ "server.",
324
+
325
+ NULL
326
+};
327
+
328
static BlockDriver bdrv_nbd = {
329
.format_name = "nbd",
330
.protocol_name = "nbd",
331
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
332
.bdrv_refresh_filename = nbd_refresh_filename,
333
.bdrv_co_block_status = nbd_client_co_block_status,
334
.bdrv_dirname = nbd_dirname,
335
+ .strong_runtime_opts = nbd_strong_runtime_opts,
336
};
337
338
static BlockDriver bdrv_nbd_tcp = {
339
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
340
.bdrv_refresh_filename = nbd_refresh_filename,
341
.bdrv_co_block_status = nbd_client_co_block_status,
342
.bdrv_dirname = nbd_dirname,
343
+ .strong_runtime_opts = nbd_strong_runtime_opts,
344
};
345
346
static BlockDriver bdrv_nbd_unix = {
347
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
348
.bdrv_refresh_filename = nbd_refresh_filename,
349
.bdrv_co_block_status = nbd_client_co_block_status,
350
.bdrv_dirname = nbd_dirname,
351
+ .strong_runtime_opts = nbd_strong_runtime_opts,
352
};
353
354
static void bdrv_nbd_init(void)
355
diff --git a/block/nfs.c b/block/nfs.c
356
index XXXXXXX..XXXXXXX 100644
357
--- a/block/nfs.c
358
+++ b/block/nfs.c
359
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
360
}
361
#endif
362
363
+static const char *nfs_strong_runtime_opts[] = {
364
+ "path",
365
+ "user",
366
+ "group",
367
+ "server.",
368
+
369
+ NULL
370
+};
371
+
372
static BlockDriver bdrv_nfs = {
373
.format_name = "nfs",
374
.protocol_name = "nfs",
375
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
376
.bdrv_refresh_filename = nfs_refresh_filename,
377
.bdrv_dirname = nfs_dirname,
378
379
+ .strong_runtime_opts = nfs_strong_runtime_opts,
380
+
381
#ifdef LIBNFS_FEATURE_PAGECACHE
382
.bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
383
#endif
384
diff --git a/block/null.c b/block/null.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/block/null.c
387
+++ b/block/null.c
388
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs, QDict *opts)
389
bs->full_open_options = qobject_ref(opts);
390
}
391
392
+static const char *const null_strong_runtime_opts[] = {
393
+ BLOCK_OPT_SIZE,
394
+ NULL_OPT_ZEROES,
395
+
396
+ NULL
397
+};
398
+
399
static BlockDriver bdrv_null_co = {
400
.format_name = "null-co",
401
.protocol_name = "null-co",
402
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
403
.bdrv_co_block_status = null_co_block_status,
404
405
.bdrv_refresh_filename = null_refresh_filename,
406
+ .strong_runtime_opts = null_strong_runtime_opts,
407
};
408
409
static BlockDriver bdrv_null_aio = {
410
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
411
.bdrv_co_block_status = null_co_block_status,
412
413
.bdrv_refresh_filename = null_refresh_filename,
414
+ .strong_runtime_opts = null_strong_runtime_opts,
415
};
416
417
static void bdrv_null_init(void)
418
diff --git a/block/nvme.c b/block/nvme.c
419
index XXXXXXX..XXXXXXX 100644
420
--- a/block/nvme.c
421
+++ b/block/nvme.c
422
@@ -XXX,XX +XXX,XX @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host)
423
qemu_vfio_dma_unmap(s->vfio, host);
424
}
425
426
+static const char *const nvme_strong_runtime_opts[] = {
427
+ NVME_BLOCK_OPT_DEVICE,
428
+ NVME_BLOCK_OPT_NAMESPACE,
429
+
430
+ NULL
431
+};
432
+
433
static BlockDriver bdrv_nvme = {
434
.format_name = "nvme",
435
.protocol_name = "nvme",
436
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nvme = {
437
438
.bdrv_refresh_filename = nvme_refresh_filename,
439
.bdrv_refresh_limits = nvme_refresh_limits,
440
+ .strong_runtime_opts = nvme_strong_runtime_opts,
441
442
.bdrv_detach_aio_context = nvme_detach_aio_context,
443
.bdrv_attach_aio_context = nvme_attach_aio_context,
444
diff --git a/block/qcow.c b/block/qcow.c
445
index XXXXXXX..XXXXXXX 100644
446
--- a/block/qcow.c
447
+++ b/block/qcow.c
448
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow_create_opts = {
449
}
450
};
451
452
+static const char *const qcow_strong_runtime_opts[] = {
453
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
454
+
455
+ NULL
456
+};
457
+
458
static BlockDriver bdrv_qcow = {
459
.format_name    = "qcow",
460
.instance_size    = sizeof(BDRVQcowState),
461
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qcow = {
462
.bdrv_get_info = qcow_get_info,
463
464
.create_opts = &qcow_create_opts,
465
+ .strong_runtime_opts = qcow_strong_runtime_opts,
466
};
467
468
static void bdrv_qcow_init(void)
469
diff --git a/block/qcow2.c b/block/qcow2.c
470
index XXXXXXX..XXXXXXX 100644
471
--- a/block/qcow2.c
472
+++ b/block/qcow2.c
473
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
474
}
475
};
476
477
+static const char *const qcow2_strong_runtime_opts[] = {
478
+ "encrypt." BLOCK_CRYPTO_OPT_QCOW_KEY_SECRET,
479
+
480
+ NULL
481
+};
482
+
483
BlockDriver bdrv_qcow2 = {
484
.format_name = "qcow2",
485
.instance_size = sizeof(BDRVQcow2State),
486
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
487
.bdrv_inactivate = qcow2_inactivate,
488
489
.create_opts = &qcow2_create_opts,
490
+ .strong_runtime_opts = qcow2_strong_runtime_opts,
491
.bdrv_co_check = qcow2_co_check,
492
.bdrv_amend_options = qcow2_amend_options,
493
494
diff --git a/block/quorum.c b/block/quorum.c
495
index XXXXXXX..XXXXXXX 100644
496
--- a/block/quorum.c
497
+++ b/block/quorum.c
498
@@ -XXX,XX +XXX,XX @@ static char *quorum_dirname(BlockDriverState *bs, Error **errp)
499
return NULL;
500
}
501
502
+static const char *const quorum_strong_runtime_opts[] = {
503
+ QUORUM_OPT_VOTE_THRESHOLD,
504
+ QUORUM_OPT_BLKVERIFY,
505
+ QUORUM_OPT_REWRITE,
506
+ QUORUM_OPT_READ_PATTERN,
507
+
508
+ NULL
509
+};
510
+
511
static BlockDriver bdrv_quorum = {
512
.format_name = "quorum",
513
514
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
515
516
.is_filter = true,
517
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
518
+
519
+ .strong_runtime_opts = quorum_strong_runtime_opts,
520
};
521
522
static void bdrv_quorum_init(void)
523
diff --git a/block/raw-format.c b/block/raw-format.c
524
index XXXXXXX..XXXXXXX 100644
525
--- a/block/raw-format.c
526
+++ b/block/raw-format.c
527
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
528
read_flags, write_flags);
529
}
530
531
+static const char *const raw_strong_runtime_opts[] = {
532
+ "offset",
533
+ "size",
534
+
535
+ NULL
536
+};
537
+
538
BlockDriver bdrv_raw = {
539
.format_name = "raw",
540
.instance_size = sizeof(BDRVRawState),
541
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
542
.bdrv_lock_medium = &raw_lock_medium,
543
.bdrv_co_ioctl = &raw_co_ioctl,
544
.create_opts = &raw_create_opts,
545
- .bdrv_has_zero_init = &raw_has_zero_init
546
+ .bdrv_has_zero_init = &raw_has_zero_init,
547
+ .strong_runtime_opts = raw_strong_runtime_opts,
548
};
549
550
static void bdrv_raw_init(void)
551
diff --git a/block/rbd.c b/block/rbd.c
552
index XXXXXXX..XXXXXXX 100644
553
--- a/block/rbd.c
554
+++ b/block/rbd.c
555
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_rbd_create_opts = {
556
}
557
};
558
559
+static const char *const qemu_rbd_strong_runtime_opts[] = {
560
+ "pool",
561
+ "image",
562
+ "conf",
563
+ "snapshot",
564
+ "user",
565
+ "server.",
566
+ "password-secret",
567
+
568
+ NULL
569
+};
570
+
571
static BlockDriver bdrv_rbd = {
572
.format_name = "rbd",
573
.instance_size = sizeof(BDRVRBDState),
574
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
575
#ifdef LIBRBD_SUPPORTS_INVALIDATE
576
.bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache,
577
#endif
578
+
579
+ .strong_runtime_opts = qemu_rbd_strong_runtime_opts,
580
};
581
582
static void bdrv_rbd_init(void)
583
diff --git a/block/replication.c b/block/replication.c
584
index XXXXXXX..XXXXXXX 100644
585
--- a/block/replication.c
586
+++ b/block/replication.c
587
@@ -XXX,XX +XXX,XX @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
588
aio_context_release(aio_context);
589
}
590
591
+static const char *const replication_strong_runtime_opts[] = {
592
+ REPLICATION_MODE,
593
+ REPLICATION_TOP_ID,
594
+
595
+ NULL
596
+};
597
+
598
BlockDriver bdrv_replication = {
599
.format_name = "replication",
600
.instance_size = sizeof(BDRVReplicationState),
601
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_replication = {
602
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
603
604
.has_variable_length = true,
605
+ .strong_runtime_opts = replication_strong_runtime_opts,
606
};
607
608
static void bdrv_replication_init(void)
609
diff --git a/block/sheepdog.c b/block/sheepdog.c
610
index XXXXXXX..XXXXXXX 100644
611
--- a/block/sheepdog.c
612
+++ b/block/sheepdog.c
613
@@ -XXX,XX +XXX,XX @@ static QemuOptsList sd_create_opts = {
614
}
615
};
616
617
+static const char *const sd_strong_runtime_opts[] = {
618
+ "vdi",
619
+ "snap-id",
620
+ "tag",
621
+ "server.",
622
+
623
+ NULL
624
+};
625
+
626
static BlockDriver bdrv_sheepdog = {
627
.format_name = "sheepdog",
628
.protocol_name = "sheepdog",
629
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
630
.bdrv_attach_aio_context = sd_attach_aio_context,
631
632
.create_opts = &sd_create_opts,
633
+ .strong_runtime_opts = sd_strong_runtime_opts,
634
};
635
636
static BlockDriver bdrv_sheepdog_tcp = {
637
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
638
.bdrv_attach_aio_context = sd_attach_aio_context,
639
640
.create_opts = &sd_create_opts,
641
+ .strong_runtime_opts = sd_strong_runtime_opts,
642
};
643
644
static BlockDriver bdrv_sheepdog_unix = {
645
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
646
.bdrv_attach_aio_context = sd_attach_aio_context,
647
648
.create_opts = &sd_create_opts,
649
+ .strong_runtime_opts = sd_strong_runtime_opts,
650
};
651
652
static void bdrv_sheepdog_init(void)
653
diff --git a/block/ssh.c b/block/ssh.c
654
index XXXXXXX..XXXXXXX 100644
655
--- a/block/ssh.c
656
+++ b/block/ssh.c
657
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
658
return ssh_grow_file(s, offset, errp);
659
}
660
661
+static const char *const ssh_strong_runtime_opts[] = {
662
+ "host",
663
+ "port",
664
+ "path",
665
+ "user",
666
+ "host_key_check",
667
+ "server.",
668
+
669
+ NULL
670
+};
671
+
672
static BlockDriver bdrv_ssh = {
673
.format_name = "ssh",
674
.protocol_name = "ssh",
675
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
676
.bdrv_co_truncate = ssh_co_truncate,
677
.bdrv_co_flush_to_disk = ssh_co_flush,
678
.create_opts = &ssh_create_opts,
679
+ .strong_runtime_opts = ssh_strong_runtime_opts,
680
};
681
682
static void bdrv_ssh_init(void)
683
diff --git a/block/throttle.c b/block/throttle.c
684
index XXXXXXX..XXXXXXX 100644
685
--- a/block/throttle.c
686
+++ b/block/throttle.c
687
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn throttle_co_drain_end(BlockDriverState *bs)
688
atomic_dec(&tgm->io_limits_disabled);
689
}
690
691
+static const char *const throttle_strong_runtime_opts[] = {
692
+ QEMU_OPT_THROTTLE_GROUP_NAME,
693
+
694
+ NULL
695
+};
696
+
697
static BlockDriver bdrv_throttle = {
698
.format_name = "throttle",
699
.instance_size = sizeof(ThrottleGroupMember),
700
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_throttle = {
701
.bdrv_co_drain_end = throttle_co_drain_end,
702
703
.is_filter = true,
704
+ .strong_runtime_opts = throttle_strong_runtime_opts,
705
};
706
707
static void bdrv_throttle_init(void)
7
diff --git a/block/vpc.c b/block/vpc.c
708
diff --git a/block/vpc.c b/block/vpc.c
8
index XXXXXXX..XXXXXXX 100644
709
index XXXXXXX..XXXXXXX 100644
9
--- a/block/vpc.c
710
--- a/block/vpc.c
10
+++ b/block/vpc.c
711
+++ b/block/vpc.c
11
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
712
@@ -XXX,XX +XXX,XX @@ static QemuOptsList vpc_create_opts = {
12
}
713
}
13
714
};
14
qemu_co_mutex_init(&s->lock);
715
15
+ qemu_opts_del(opts);
716
+static const char *const vpc_strong_runtime_opts[] = {
16
717
+ VPC_OPT_SIZE_CALC,
17
return 0;
718
+
18
719
+ NULL
19
fail:
720
+};
20
+ qemu_opts_del(opts);
721
+
21
qemu_vfree(s->pagetable);
722
static BlockDriver bdrv_vpc = {
22
#ifdef CACHE
723
.format_name = "vpc",
23
g_free(s->pageentry_u8);
724
.instance_size = sizeof(BDRVVPCState),
725
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vpc = {
726
727
.create_opts = &vpc_create_opts,
728
.bdrv_has_zero_init = vpc_has_zero_init,
729
+ .strong_runtime_opts = vpc_strong_runtime_opts,
730
};
731
732
static void bdrv_vpc_init(void)
733
diff --git a/block/vvfat.c b/block/vvfat.c
734
index XXXXXXX..XXXXXXX 100644
735
--- a/block/vvfat.c
736
+++ b/block/vvfat.c
737
@@ -XXX,XX +XXX,XX @@ static void vvfat_close(BlockDriverState *bs)
738
}
739
}
740
741
+static const char *const vvfat_strong_runtime_opts[] = {
742
+ "dir",
743
+ "fat-type",
744
+ "floppy",
745
+ "label",
746
+ "rw",
747
+
748
+ NULL
749
+};
750
+
751
static BlockDriver bdrv_vvfat = {
752
.format_name = "vvfat",
753
.protocol_name = "fat",
754
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vvfat = {
755
.bdrv_co_preadv = vvfat_co_preadv,
756
.bdrv_co_pwritev = vvfat_co_pwritev,
757
.bdrv_co_block_status = vvfat_co_block_status,
758
+
759
+ .strong_runtime_opts = vvfat_strong_runtime_opts,
760
};
761
762
static void bdrv_vvfat_init(void)
763
diff --git a/block/vxhs.c b/block/vxhs.c
764
index XXXXXXX..XXXXXXX 100644
765
--- a/block/vxhs.c
766
+++ b/block/vxhs.c
767
@@ -XXX,XX +XXX,XX @@ static int64_t vxhs_getlength(BlockDriverState *bs)
768
return vdisk_size;
769
}
770
771
+static const char *const vxhs_strong_runtime_opts[] = {
772
+ VXHS_OPT_VDISK_ID,
773
+ "tls-creds",
774
+ VXHS_OPT_HOST,
775
+ VXHS_OPT_PORT,
776
+ VXHS_OPT_SERVER".",
777
+
778
+ NULL
779
+};
780
+
781
static BlockDriver bdrv_vxhs = {
782
.format_name = "vxhs",
783
.protocol_name = "vxhs",
784
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vxhs = {
785
.bdrv_getlength = vxhs_getlength,
786
.bdrv_aio_preadv = vxhs_aio_preadv,
787
.bdrv_aio_pwritev = vxhs_aio_pwritev,
788
+ .strong_runtime_opts = vxhs_strong_runtime_opts,
789
};
790
791
static void bdrv_vxhs_init(void)
24
--
792
--
25
2.19.1
793
2.20.1
26
794
27
795
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This is a static function with only one caller, so there's no need to
3
Some follow-up patches will rework the way bs->full_open_options is
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
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.
5
8
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
However, by implementing bdrv_gather_child_options(), block drivers will
7
Reported-by: Markus Armbruster <armbru@redhat.com>
10
still be able to override the way the full_open_options of their
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
children are incorporated into their own.
12
13
We need to implement this function for VMDK because we have to prevent
14
the generic implementation from gathering the options of all children:
15
It is not possible to specify options for the extents through the
16
runtime options.
17
18
For quorum, the child names that would be used by the generic
19
implementation and the ones that we actually (currently) want to use
20
differ. See quorum_gather_child_options() for more information.
21
22
Note that both of these are cases which are not ideal: In case of VMDK
23
it would probably be nice to be able to specify options for all extents.
24
In case of quorum, the current runtime option structure is simply broken
25
and needs to be fixed (but that is left for another patch).
26
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
Reviewed-by: Alberto Garcia <berto@igalia.com>
29
Message-id: 20190201192935.18394-23-mreitz@redhat.com
30
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
31
---
10
block/quorum.c | 24 +++++-------------------
32
include/block/block_int.h | 24 +++++++++++++++++++++++
11
1 file changed, 5 insertions(+), 19 deletions(-)
33
block/quorum.c | 40 +++++++++++++++++++++++++++++++++++++++
34
block/vmdk.c | 19 +++++++++++++++++++
35
3 files changed, 83 insertions(+)
12
36
37
diff --git a/include/block/block_int.h b/include/block/block_int.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block_int.h
40
+++ b/include/block/block_int.h
41
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
42
43
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
44
45
+ /*
46
+ * Gathers the open options for all children into @target.
47
+ * A simple format driver (without backing file support) might
48
+ * implement this function like this:
49
+ *
50
+ * QINCREF(bs->file->bs->full_open_options);
51
+ * qdict_put(target, "file", bs->file->bs->full_open_options);
52
+ *
53
+ * If not specified, the generic implementation will simply put
54
+ * all children's options under their respective name.
55
+ *
56
+ * @backing_overridden is true when bs->backing seems not to be
57
+ * the child that would result from opening bs->backing_file.
58
+ * Therefore, if it is true, the backing child's options should be
59
+ * gathered; otherwise, there is no need since the backing child
60
+ * is the one implied by the image header.
61
+ *
62
+ * Note that ideally this function would not be needed. Every
63
+ * block driver which implements it is probably doing something
64
+ * shady regarding its runtime option structure.
65
+ */
66
+ void (*bdrv_gather_child_options)(BlockDriverState *bs, QDict *target,
67
+ bool backing_overridden);
68
+
69
/*
70
* Returns an allocated string which is the directory name of this BDS: It
71
* will be used to make relative filenames absolute by prepending this
13
diff --git a/block/quorum.c b/block/quorum.c
72
diff --git a/block/quorum.c b/block/quorum.c
14
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
15
--- a/block/quorum.c
74
--- a/block/quorum.c
16
+++ b/block/quorum.c
75
+++ b/block/quorum.c
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
76
@@ -XXX,XX +XXX,XX @@ static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
18
return true;
77
bs->full_open_options = opts;
19
}
78
}
20
79
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
80
+static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
22
- const char *fmt, ...)
81
+ bool backing_overridden)
23
-{
82
+{
24
- va_list ap;
83
+ BDRVQuorumState *s = bs->opaque;
25
-
84
+ QList *children_list;
26
- va_start(ap, fmt);
85
+ int i;
27
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
86
+
28
- acb->offset, acb->bytes);
87
+ /*
29
- vfprintf(stderr, fmt, ap);
88
+ * The generic implementation for gathering child options in
30
- fprintf(stderr, "\n");
89
+ * bdrv_refresh_filename() would use the names of the children
31
- va_end(ap);
90
+ * as specified for bdrv_open_child() or bdrv_attach_child(),
32
- exit(1);
91
+ * which is "children.%u" with %u being a value
33
-}
92
+ * (s->next_child_index) that is incremented each time a new child
34
-
93
+ * is added (and never decremented). Since children can be
35
-static bool quorum_compare(QuorumAIOCB *acb,
94
+ * deleted at runtime, there may be gaps in that enumeration.
36
- QEMUIOVector *a,
95
+ * When creating a new quorum BDS and specifying the children for
37
- QEMUIOVector *b)
96
+ * it through runtime options, the enumeration used there may not
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
97
+ * have any gaps, though.
98
+ *
99
+ * Therefore, we have to create a new gap-less enumeration here
100
+ * (which we can achieve by simply putting all of the children's
101
+ * full_open_options into a QList).
102
+ *
103
+ * XXX: Note that there are issues with the current child option
104
+ * structure quorum uses (such as the fact that children do
105
+ * not really have unique permanent names). Therefore, this
106
+ * is going to have to change in the future and ideally we
107
+ * want quorum to be covered by the generic implementation.
108
+ */
109
+
110
+ children_list = qlist_new();
111
+ qdict_put(target, "children", children_list);
112
+
113
+ for (i = 0; i < s->num_children; i++) {
114
+ qlist_append(children_list,
115
+ qobject_ref(s->children[i]->bs->full_open_options));
116
+ }
117
+}
118
+
119
static char *quorum_dirname(BlockDriverState *bs, Error **errp)
39
{
120
{
40
BDRVQuorumState *s = acb->bs->opaque;
121
/* In general, there are multiple BDSs with different dirnames below this
41
ssize_t offset;
122
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
123
.bdrv_open = quorum_open,
43
if (s->is_blkverify) {
124
.bdrv_close = quorum_close,
44
offset = qemu_iovec_compare(a, b);
125
.bdrv_refresh_filename = quorum_refresh_filename,
45
if (offset != -1) {
126
+ .bdrv_gather_child_options = quorum_gather_child_options,
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
127
.bdrv_dirname = quorum_dirname,
47
- acb->offset + offset);
128
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
129
.bdrv_co_flush_to_disk = quorum_co_flush,
49
+ " contents mismatch at offset %" PRIu64 "\n",
130
diff --git a/block/vmdk.c b/block/vmdk.c
50
+ acb->offset, acb->bytes, acb->offset + offset);
131
index XXXXXXX..XXXXXXX 100644
51
+ exit(1);
132
--- a/block/vmdk.c
52
}
133
+++ b/block/vmdk.c
53
return true;
134
@@ -XXX,XX +XXX,XX @@
54
}
135
#include "qapi/error.h"
136
#include "block/block_int.h"
137
#include "sysemu/block-backend.h"
138
+#include "qapi/qmp/qdict.h"
139
#include "qapi/qmp/qerror.h"
140
#include "qemu/error-report.h"
141
#include "qemu/module.h"
142
@@ -XXX,XX +XXX,XX @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
143
return 0;
144
}
145
146
+static void vmdk_gather_child_options(BlockDriverState *bs, QDict *target,
147
+ bool backing_overridden)
148
+{
149
+ /* No children but file and backing can be explicitly specified (TODO) */
150
+ qdict_put(target, "file",
151
+ qobject_ref(bs->file->bs->full_open_options));
152
+
153
+ if (backing_overridden) {
154
+ if (bs->backing) {
155
+ qdict_put(target, "backing",
156
+ qobject_ref(bs->backing->bs->full_open_options));
157
+ } else {
158
+ qdict_put_null(target, "backing");
159
+ }
160
+ }
161
+}
162
+
163
static QemuOptsList vmdk_create_opts = {
164
.name = "vmdk-create-opts",
165
.head = QTAILQ_HEAD_INITIALIZER(vmdk_create_opts.head),
166
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
167
.bdrv_get_specific_info = vmdk_get_specific_info,
168
.bdrv_refresh_limits = vmdk_refresh_limits,
169
.bdrv_get_info = vmdk_get_info,
170
+ .bdrv_gather_child_options = vmdk_gather_child_options,
171
172
.supports_backing = true,
173
.create_opts = &vmdk_create_opts,
55
--
174
--
56
2.19.1
175
2.20.1
57
176
58
177
diff view generated by jsdifflib
New patch
1
1
From: Max Reitz <mreitz@redhat.com>
2
3
Instead of having every block driver which implements
4
bdrv_refresh_filename() copy all of the strong runtime options over to
5
bs->full_open_options, implement this process generically in
6
bdrv_refresh_filename().
7
8
This patch only adds this new generic implementation, it does not remove
9
the old functionality. This is done in a follow-up patch.
10
11
With this patch, some superfluous information (that should never have
12
been there) may be removed from some JSON filenames, as can be seen in
13
the change to iotests 110's and 228's reference outputs.
14
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Message-id: 20190201192935.18394-24-mreitz@redhat.com
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block.c | 116 ++++++++++++++++++++++++++++++++++++-
20
tests/qemu-iotests/110.out | 2 +-
21
tests/qemu-iotests/228 | 7 ++-
22
tests/qemu-iotests/228.out | 2 +-
23
4 files changed, 121 insertions(+), 6 deletions(-)
24
25
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
28
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ out:
30
return to_replace_bs;
31
}
32
33
+/**
34
+ * Iterates through the list of runtime option keys that are said to
35
+ * be "strong" for a BDS. An option is called "strong" if it changes
36
+ * a BDS's data. For example, the null block driver's "size" and
37
+ * "read-zeroes" options are strong, but its "latency-ns" option is
38
+ * not.
39
+ *
40
+ * If a key returned by this function ends with a dot, all options
41
+ * starting with that prefix are strong.
42
+ */
43
+static const char *const *strong_options(BlockDriverState *bs,
44
+ const char *const *curopt)
45
+{
46
+ static const char *const global_options[] = {
47
+ "driver", "filename", NULL
48
+ };
49
+
50
+ if (!curopt) {
51
+ return &global_options[0];
52
+ }
53
+
54
+ curopt++;
55
+ if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) {
56
+ curopt = bs->drv->strong_runtime_opts;
57
+ }
58
+
59
+ return (curopt && *curopt) ? curopt : NULL;
60
+}
61
+
62
+/**
63
+ * Copies all strong runtime options from bs->options to the given
64
+ * QDict. The set of strong option keys is determined by invoking
65
+ * strong_options().
66
+ *
67
+ * Returns true iff any strong option was present in bs->options (and
68
+ * thus copied to the target QDict) with the exception of "filename"
69
+ * and "driver". The caller is expected to use this value to decide
70
+ * whether the existence of strong options prevents the generation of
71
+ * a plain filename.
72
+ */
73
+static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
74
+{
75
+ bool found_any = false;
76
+ const char *const *option_name = NULL;
77
+
78
+ if (!bs->drv) {
79
+ return false;
80
+ }
81
+
82
+ while ((option_name = strong_options(bs, option_name))) {
83
+ bool option_given = false;
84
+
85
+ assert(strlen(*option_name) > 0);
86
+ if ((*option_name)[strlen(*option_name) - 1] != '.') {
87
+ QObject *entry = qdict_get(bs->options, *option_name);
88
+ if (!entry) {
89
+ continue;
90
+ }
91
+
92
+ qdict_put_obj(d, *option_name, qobject_ref(entry));
93
+ option_given = true;
94
+ } else {
95
+ const QDictEntry *entry;
96
+ for (entry = qdict_first(bs->options); entry;
97
+ entry = qdict_next(bs->options, entry))
98
+ {
99
+ if (strstart(qdict_entry_key(entry), *option_name, NULL)) {
100
+ qdict_put_obj(d, qdict_entry_key(entry),
101
+ qobject_ref(qdict_entry_value(entry)));
102
+ option_given = true;
103
+ }
104
+ }
105
+ }
106
+
107
+ /* While "driver" and "filename" need to be included in a JSON filename,
108
+ * their existence does not prohibit generation of a plain filename. */
109
+ if (!found_any && option_given &&
110
+ strcmp(*option_name, "driver") && strcmp(*option_name, "filename"))
111
+ {
112
+ found_any = true;
113
+ }
114
+ }
115
+
116
+ return found_any;
117
+}
118
+
119
static bool append_open_options(QDict *d, BlockDriverState *bs)
120
{
121
const QDictEntry *entry;
122
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
123
bs->full_open_options = opts;
124
}
125
126
+ /* Gather the options QDict */
127
+ opts = qdict_new();
128
+ append_strong_runtime_options(opts, bs);
129
+
130
+ if (drv->bdrv_gather_child_options) {
131
+ /* Some block drivers may not want to present all of their children's
132
+ * options, or name them differently from BdrvChild.name */
133
+ drv->bdrv_gather_child_options(bs, opts, backing_overridden);
134
+ } else {
135
+ QLIST_FOREACH(child, &bs->children, next) {
136
+ if (child->role == &child_backing && !backing_overridden) {
137
+ /* We can skip the backing BDS if it has not been overridden */
138
+ continue;
139
+ }
140
+
141
+ qdict_put(opts, child->name,
142
+ qobject_ref(child->bs->full_open_options));
143
+ }
144
+
145
+ if (backing_overridden && !bs->backing) {
146
+ /* Force no backing file */
147
+ qdict_put_null(opts, "backing");
148
+ }
149
+ }
150
+
151
+ qobject_unref(bs->full_open_options);
152
+ bs->full_open_options = opts;
153
+
154
if (bs->exact_filename[0]) {
155
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
156
- } else if (bs->full_open_options) {
157
+ } else {
158
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
159
snprintf(bs->filename, sizeof(bs->filename), "json:%s",
160
qstring_get_str(json));
161
diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out
162
index XXXXXXX..XXXXXXX 100644
163
--- a/tests/qemu-iotests/110.out
164
+++ b/tests/qemu-iotests/110.out
165
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b
166
167
=== Nodes without a common directory ===
168
169
-image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "blkverify": false, "rewrite-corrupted": false, "vote-threshold": 1}}
170
+image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}}
171
file format: IMGFMT
172
virtual size: 64M (67108864 bytes)
173
backing file: t.IMGFMT.base (cannot determine actual path)
174
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
175
index XXXXXXX..XXXXXXX 100755
176
--- a/tests/qemu-iotests/228
177
+++ b/tests/qemu-iotests/228
178
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
179
overlay='node0')
180
181
# This should give us the original plain result
182
- # FIXME: Currently, the block layer considers the runtime backing
183
- # file to be different from the image header, which is
184
- # wrong. This is fixed by a future patch.
185
+ # FIXME: Currently, it yields a json:{} filename even though it
186
+ # only contains a @driver and a @file entry, so a plain
187
+ # filename would obviously suffice. This is fixed by a
188
+ # future patch.
189
190
log_node_info(vm.node_info('node0'))
191
192
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
193
index XXXXXXX..XXXXXXX 100644
194
--- a/tests/qemu-iotests/228.out
195
+++ b/tests/qemu-iotests/228.out
196
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
197
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
198
{"return": {}}
199
200
-bs->filename: json:{"backing": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
201
+bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
202
bs->backing_file: TEST_DIR/PID-base.img
203
bs->backing->bs->filename: TEST_DIR/PID-base.img
204
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
New patch
1
1
From: Max Reitz <mreitz@redhat.com>
2
3
Currently, BlockDriver.bdrv_refresh_filename() is supposed to both
4
refresh the filename (BDS.exact_filename) and set BDS.full_open_options.
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
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
Message-id: 20190201192935.18394-25-mreitz@redhat.com
26
Signed-off-by: Max Reitz <mreitz@redhat.com>
27
---
28
include/block/block_int.h | 6 +-
29
block.c | 131 +++++++------------------------------
30
block/blkdebug.c | 54 ++++++---------
31
block/blklogwrites.c | 22 -------
32
block/blkverify.c | 16 +----
33
block/commit.c | 2 +-
34
block/mirror.c | 2 +-
35
block/nbd.c | 23 +------
36
block/nfs.c | 36 +---------
37
block/null.c | 22 ++++---
38
block/nvme.c | 22 ++++---
39
block/quorum.c | 30 ---------
40
tests/qemu-iotests/228 | 4 --
41
tests/qemu-iotests/228.out | 2 +-
42
14 files changed, 81 insertions(+), 291 deletions(-)
43
44
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int.h
47
+++ b/include/block/block_int.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
Error **errp);
50
int (*bdrv_make_empty)(BlockDriverState *bs);
51
52
- void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
53
+ /*
54
+ * Refreshes the bs->exact_filename field. If that is impossible,
55
+ * bs->exact_filename has to be left empty.
56
+ */
57
+ void (*bdrv_refresh_filename)(BlockDriverState *bs);
58
59
/*
60
* Gathers the open options for all children into @target.
61
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
64
+++ b/block.c
65
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
66
return found_any;
67
}
68
69
-static bool append_open_options(QDict *d, BlockDriverState *bs)
70
-{
71
- const QDictEntry *entry;
72
- QemuOptDesc *desc;
73
- bool found_any = false;
74
-
75
- for (entry = qdict_first(bs->options); entry;
76
- entry = qdict_next(bs->options, entry))
77
- {
78
- /* Exclude all non-driver-specific options */
79
- for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
80
- if (!strcmp(qdict_entry_key(entry), desc->name)) {
81
- break;
82
- }
83
- }
84
- if (desc->name) {
85
- continue;
86
- }
87
-
88
- qdict_put_obj(d, qdict_entry_key(entry),
89
- qobject_ref(qdict_entry_value(entry)));
90
- found_any = true;
91
- }
92
-
93
- return found_any;
94
-}
95
-
96
/* Note: This function may return false positives; it may return true
97
* even if opening the backing file specified by bs's image header
98
* would result in exactly bs->backing. */
99
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
100
BdrvChild *child;
101
QDict *opts;
102
bool backing_overridden;
103
+ bool generate_json_filename; /* Whether our default implementation should
104
+ fill exact_filename (false) or not (true) */
105
106
if (!drv) {
107
return;
108
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
109
backing_overridden = false;
110
}
111
112
- if (drv->bdrv_refresh_filename) {
113
- /* Obsolete information is of no use here, so drop the old file name
114
- * information before refreshing it */
115
- bs->exact_filename[0] = '\0';
116
- if (bs->full_open_options) {
117
- qobject_unref(bs->full_open_options);
118
- bs->full_open_options = NULL;
119
- }
120
-
121
- opts = qdict_new();
122
- append_open_options(opts, bs);
123
- drv->bdrv_refresh_filename(bs, opts);
124
- qobject_unref(opts);
125
- } else if (bs->file) {
126
- /* Try to reconstruct valid information from the underlying file */
127
- bool has_open_options;
128
-
129
- bs->exact_filename[0] = '\0';
130
- if (bs->full_open_options) {
131
- qobject_unref(bs->full_open_options);
132
- bs->full_open_options = NULL;
133
- }
134
-
135
- opts = qdict_new();
136
- has_open_options = append_open_options(opts, bs);
137
- has_open_options |= backing_overridden;
138
-
139
- /* If no specific options have been given for this BDS, the filename of
140
- * the underlying file should suffice for this one as well */
141
- if (bs->file->bs->exact_filename[0] && !has_open_options) {
142
- strcpy(bs->exact_filename, bs->file->bs->exact_filename);
143
- }
144
- /* Reconstructing the full options QDict is simple for most format block
145
- * drivers, as long as the full options are known for the underlying
146
- * file BDS. The full options QDict of that file BDS should somehow
147
- * contain a representation of the filename, therefore the following
148
- * suffices without querying the (exact_)filename of this BDS. */
149
- if (bs->file->bs->full_open_options &&
150
- (!bs->backing || bs->backing->bs->full_open_options))
151
- {
152
- qdict_put_str(opts, "driver", drv->format_name);
153
- qdict_put(opts, "file",
154
- qobject_ref(bs->file->bs->full_open_options));
155
-
156
- if (bs->backing) {
157
- qdict_put(opts, "backing",
158
- qobject_ref(bs->backing->bs->full_open_options));
159
- } else if (backing_overridden) {
160
- qdict_put_null(opts, "backing");
161
- }
162
-
163
- bs->full_open_options = opts;
164
- } else {
165
- qobject_unref(opts);
166
- }
167
- } else if (!bs->full_open_options && qdict_size(bs->options)) {
168
- /* There is no underlying file BDS (at least referenced by BDS.file),
169
- * so the full options QDict should be equal to the options given
170
- * specifically for this block device when it was opened (plus the
171
- * driver specification).
172
- * Because those options don't change, there is no need to update
173
- * full_open_options when it's already set. */
174
-
175
- opts = qdict_new();
176
- append_open_options(opts, bs);
177
- qdict_put_str(opts, "driver", drv->format_name);
178
-
179
- if (bs->exact_filename[0]) {
180
- /* This may not work for all block protocol drivers (some may
181
- * require this filename to be parsed), but we have to find some
182
- * default solution here, so just include it. If some block driver
183
- * does not support pure options without any filename at all or
184
- * needs some special format of the options QDict, it needs to
185
- * implement the driver-specific bdrv_refresh_filename() function.
186
- */
187
- qdict_put_str(opts, "filename", bs->exact_filename);
188
- }
189
-
190
- bs->full_open_options = opts;
191
- }
192
-
193
/* Gather the options QDict */
194
opts = qdict_new();
195
- append_strong_runtime_options(opts, bs);
196
+ generate_json_filename = append_strong_runtime_options(opts, bs);
197
+ generate_json_filename |= backing_overridden;
198
199
if (drv->bdrv_gather_child_options) {
200
/* Some block drivers may not want to present all of their children's
201
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
202
qobject_unref(bs->full_open_options);
203
bs->full_open_options = opts;
204
205
+ if (drv->bdrv_refresh_filename) {
206
+ /* Obsolete information is of no use here, so drop the old file name
207
+ * information before refreshing it */
208
+ bs->exact_filename[0] = '\0';
209
+
210
+ drv->bdrv_refresh_filename(bs);
211
+ } else if (bs->file) {
212
+ /* Try to reconstruct valid information from the underlying file */
213
+
214
+ bs->exact_filename[0] = '\0';
215
+
216
+ /* If no specific options have been given for this BDS, the filename of
217
+ * the underlying file should suffice for this one as well */
218
+ if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
219
+ strcpy(bs->exact_filename, bs->file->bs->exact_filename);
220
+ }
221
+ }
222
+
223
if (bs->exact_filename[0]) {
224
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
225
} else {
226
diff --git a/block/blkdebug.c b/block/blkdebug.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/block/blkdebug.c
229
+++ b/block/blkdebug.c
230
@@ -XXX,XX +XXX,XX @@ static int64_t blkdebug_getlength(BlockDriverState *bs)
231
return bdrv_getlength(bs->file->bs);
232
}
233
234
-static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
235
+static void blkdebug_refresh_filename(BlockDriverState *bs)
236
{
237
BDRVBlkdebugState *s = bs->opaque;
238
- QDict *opts;
239
const QDictEntry *e;
240
- bool force_json = false;
241
-
242
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
243
- if (strcmp(qdict_entry_key(e), "config") &&
244
- strcmp(qdict_entry_key(e), "x-image"))
245
- {
246
- force_json = true;
247
- break;
248
- }
249
- }
250
+ int ret;
251
252
- if (force_json && !bs->file->bs->full_open_options) {
253
- /* The config file cannot be recreated, so creating a plain filename
254
- * is impossible */
255
+ if (!bs->file->bs->exact_filename[0]) {
256
return;
257
}
258
259
- if (!force_json && bs->file->bs->exact_filename[0]) {
260
- int ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
261
- "blkdebug:%s:%s", s->config_file ?: "",
262
- bs->file->bs->exact_filename);
263
- if (ret >= sizeof(bs->exact_filename)) {
264
- /* An overflow makes the filename unusable, so do not report any */
265
- bs->exact_filename[0] = 0;
266
+ for (e = qdict_first(bs->full_open_options); e;
267
+ e = qdict_next(bs->full_open_options, e))
268
+ {
269
+ /* Real child options are under "image", but "x-image" may
270
+ * contain a filename */
271
+ if (strcmp(qdict_entry_key(e), "config") &&
272
+ strcmp(qdict_entry_key(e), "image") &&
273
+ strcmp(qdict_entry_key(e), "x-image") &&
274
+ strcmp(qdict_entry_key(e), "driver"))
275
+ {
276
+ return;
277
}
278
}
279
280
- opts = qdict_new();
281
- qdict_put_str(opts, "driver", "blkdebug");
282
-
283
- qdict_put(opts, "image", qobject_ref(bs->file->bs->full_open_options));
284
-
285
- for (e = qdict_first(options); e; e = qdict_next(options, e)) {
286
- if (strcmp(qdict_entry_key(e), "x-image")) {
287
- qdict_put_obj(opts, qdict_entry_key(e),
288
- qobject_ref(qdict_entry_value(e)));
289
- }
290
+ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
291
+ "blkdebug:%s:%s",
292
+ s->config_file ?: "", bs->file->bs->exact_filename);
293
+ if (ret >= sizeof(bs->exact_filename)) {
294
+ /* An overflow makes the filename unusable, so do not report any */
295
+ bs->exact_filename[0] = 0;
296
}
297
-
298
- bs->full_open_options = opts;
299
}
300
301
static void blkdebug_refresh_limits(BlockDriverState *bs, Error **errp)
302
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/block/blklogwrites.c
305
+++ b/block/blklogwrites.c
306
@@ -XXX,XX +XXX,XX @@ static int64_t blk_log_writes_getlength(BlockDriverState *bs)
307
return bdrv_getlength(bs->file->bs);
308
}
309
310
-static void blk_log_writes_refresh_filename(BlockDriverState *bs,
311
- QDict *options)
312
-{
313
- BDRVBlkLogWritesState *s = bs->opaque;
314
-
315
- if (bs->file->bs->full_open_options
316
- && s->log_file->bs->full_open_options)
317
- {
318
- QDict *opts = qdict_new();
319
- qdict_put_str(opts, "driver", "blklogwrites");
320
-
321
- qobject_ref(bs->file->bs->full_open_options);
322
- qdict_put(opts, "file", bs->file->bs->full_open_options);
323
- qobject_ref(s->log_file->bs->full_open_options);
324
- qdict_put(opts, "log", s->log_file->bs->full_open_options);
325
- qdict_put_int(opts, "log-sector-size", s->sectorsize);
326
-
327
- bs->full_open_options = opts;
328
- }
329
-}
330
-
331
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
332
const BdrvChildRole *role,
333
BlockReopenQueue *ro_q,
334
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_blk_log_writes = {
335
.bdrv_open = blk_log_writes_open,
336
.bdrv_close = blk_log_writes_close,
337
.bdrv_getlength = blk_log_writes_getlength,
338
- .bdrv_refresh_filename = blk_log_writes_refresh_filename,
339
.bdrv_child_perm = blk_log_writes_child_perm,
340
.bdrv_refresh_limits = blk_log_writes_refresh_limits,
341
342
diff --git a/block/blkverify.c b/block/blkverify.c
343
index XXXXXXX..XXXXXXX 100644
344
--- a/block/blkverify.c
345
+++ b/block/blkverify.c
346
@@ -XXX,XX +XXX,XX @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
347
return bdrv_recurse_is_first_non_filter(s->test_file->bs, candidate);
348
}
349
350
-static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
351
+static void blkverify_refresh_filename(BlockDriverState *bs)
352
{
353
BDRVBlkverifyState *s = bs->opaque;
354
355
- if (bs->file->bs->full_open_options
356
- && s->test_file->bs->full_open_options)
357
- {
358
- QDict *opts = qdict_new();
359
- qdict_put_str(opts, "driver", "blkverify");
360
-
361
- qdict_put(opts, "raw",
362
- qobject_ref(bs->file->bs->full_open_options));
363
- qdict_put(opts, "test",
364
- qobject_ref(s->test_file->bs->full_open_options));
365
-
366
- bs->full_open_options = opts;
367
- }
368
-
369
if (bs->file->bs->exact_filename[0]
370
&& s->test_file->bs->exact_filename[0])
371
{
372
diff --git a/block/commit.c b/block/commit.c
373
index XXXXXXX..XXXXXXX 100644
374
--- a/block/commit.c
375
+++ b/block/commit.c
376
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_commit_top_preadv(BlockDriverState *bs,
377
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
378
}
379
380
-static void bdrv_commit_top_refresh_filename(BlockDriverState *bs, QDict *opts)
381
+static void bdrv_commit_top_refresh_filename(BlockDriverState *bs)
382
{
383
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
384
bs->backing->bs->filename);
385
diff --git a/block/mirror.c b/block/mirror.c
386
index XXXXXXX..XXXXXXX 100644
387
--- a/block/mirror.c
388
+++ b/block/mirror.c
389
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_mirror_top_pdiscard(BlockDriverState *bs,
390
NULL, 0);
391
}
392
393
-static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs, QDict *opts)
394
+static void bdrv_mirror_top_refresh_filename(BlockDriverState *bs)
395
{
396
if (bs->backing == NULL) {
397
/* we can be here after failed bdrv_attach_child in
398
diff --git a/block/nbd.c b/block/nbd.c
399
index XXXXXXX..XXXXXXX 100644
400
--- a/block/nbd.c
401
+++ b/block/nbd.c
402
@@ -XXX,XX +XXX,XX @@ static void nbd_attach_aio_context(BlockDriverState *bs,
403
nbd_client_attach_aio_context(bs, new_context);
404
}
405
406
-static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
407
+static void nbd_refresh_filename(BlockDriverState *bs)
408
{
409
BDRVNBDState *s = bs->opaque;
410
- QDict *opts = qdict_new();
411
- QObject *saddr_qdict;
412
- Visitor *ov;
413
const char *host = NULL, *port = NULL, *path = NULL;
414
415
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
416
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
417
path = s->saddr->u.q_unix.path;
418
} /* else can't represent as pseudo-filename */
419
420
- qdict_put_str(opts, "driver", "nbd");
421
-
422
if (path && s->export) {
423
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
424
"nbd+unix:///%s?socket=%s", s->export, path);
425
@@ -XXX,XX +XXX,XX @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
426
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
427
"nbd://%s:%s", host, port);
428
}
429
-
430
- ov = qobject_output_visitor_new(&saddr_qdict);
431
- visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort);
432
- visit_complete(ov, &saddr_qdict);
433
- visit_free(ov);
434
- qdict_put_obj(opts, "server", saddr_qdict);
435
-
436
- if (s->export) {
437
- qdict_put_str(opts, "export", s->export);
438
- }
439
- if (s->tlscredsid) {
440
- qdict_put_str(opts, "tls-creds", s->tlscredsid);
441
- }
442
-
443
- qdict_flatten(opts);
444
- bs->full_open_options = opts;
445
}
446
447
static char *nbd_dirname(BlockDriverState *bs, Error **errp)
448
diff --git a/block/nfs.c b/block/nfs.c
449
index XXXXXXX..XXXXXXX 100644
450
--- a/block/nfs.c
451
+++ b/block/nfs.c
452
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
453
return 0;
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
577
index XXXXXXX..XXXXXXX 100644
578
--- a/block/quorum.c
579
+++ b/block/quorum.c
580
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
581
bdrv_drained_end(bs);
582
}
583
584
-static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
585
-{
586
- BDRVQuorumState *s = bs->opaque;
587
- QDict *opts;
588
- QList *children;
589
- int i;
590
-
591
- for (i = 0; i < s->num_children; i++) {
592
- if (!s->children[i]->bs->full_open_options) {
593
- return;
594
- }
595
- }
596
-
597
- children = qlist_new();
598
- for (i = 0; i < s->num_children; i++) {
599
- qlist_append(children,
600
- qobject_ref(s->children[i]->bs->full_open_options));
601
- }
602
-
603
- opts = qdict_new();
604
- qdict_put_str(opts, "driver", "quorum");
605
- qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold);
606
- qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify);
607
- qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted);
608
- qdict_put(opts, "children", children);
609
-
610
- bs->full_open_options = opts;
611
-}
612
-
613
static void quorum_gather_child_options(BlockDriverState *bs, QDict *target,
614
bool backing_overridden)
615
{
616
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_quorum = {
617
618
.bdrv_open = quorum_open,
619
.bdrv_close = quorum_close,
620
- .bdrv_refresh_filename = quorum_refresh_filename,
621
.bdrv_gather_child_options = quorum_gather_child_options,
622
.bdrv_dirname = quorum_dirname,
623
624
diff --git a/tests/qemu-iotests/228 b/tests/qemu-iotests/228
625
index XXXXXXX..XXXXXXX 100755
626
--- a/tests/qemu-iotests/228
627
+++ b/tests/qemu-iotests/228
628
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
629
overlay='node0')
630
631
# This should give us the original plain result
632
- # FIXME: Currently, it yields a json:{} filename even though it
633
- # only contains a @driver and a @file entry, so a plain
634
- # filename would obviously suffice. This is fixed by a
635
- # future patch.
636
637
log_node_info(vm.node_info('node0'))
638
639
diff --git a/tests/qemu-iotests/228.out b/tests/qemu-iotests/228.out
640
index XXXXXXX..XXXXXXX 100644
641
--- a/tests/qemu-iotests/228.out
642
+++ b/tests/qemu-iotests/228.out
643
@@ -XXX,XX +XXX,XX @@ bs->backing: (none)
644
{"execute": "blockdev-snapshot", "arguments": {"node": "original-backing", "overlay": "node0"}}
645
{"return": {}}
646
647
-bs->filename: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}}
648
+bs->filename: TEST_DIR/PID-top.img
649
bs->backing_file: TEST_DIR/PID-base.img
650
bs->backing->bs->filename: TEST_DIR/PID-base.img
651
652
--
653
2.20.1
654
655
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
If a format BDS's file BDS is in turn a format BDS, we cannot simply use
4
the same filename, because when opening a BDS tree based on a filename
5
alone, qemu will create only one format node on top of one protocol node
6
(disregarding a potential backing file).
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20190201192935.18394-26-mreitz@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block.c | 18 +++++++++++++++---
14
1 file changed, 15 insertions(+), 3 deletions(-)
15
16
diff --git a/block.c b/block.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block.c
19
+++ b/block.c
20
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs)
21
22
bs->exact_filename[0] = '\0';
23
24
- /* If no specific options have been given for this BDS, the filename of
25
- * the underlying file should suffice for this one as well */
26
- if (bs->file->bs->exact_filename[0] && !generate_json_filename) {
27
+ /*
28
+ * We can use the underlying file's filename if:
29
+ * - it has a filename,
30
+ * - the file is a protocol BDS, and
31
+ * - opening that file (as this BDS's format) will automatically create
32
+ * the BDS tree we have right now, that is:
33
+ * - the user did not significantly change this BDS's behavior with
34
+ * some explicit (strong) options
35
+ * - no non-file child of this BDS has been overridden by the user
36
+ * Both of these conditions are represented by generate_json_filename.
37
+ */
38
+ if (bs->file->bs->exact_filename[0] &&
39
+ bs->file->bs->drv->bdrv_file_open &&
40
+ !generate_json_filename)
41
+ {
42
strcpy(bs->exact_filename, bs->file->bs->exact_filename);
43
}
44
}
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
Currently, nvme's bdrv_refresh_filename() is an exact copy of null's
4
it might not be actually aligned enough for that pointer type (and
4
implementation. However, for null, "null-co://" and "null-aio://" are
5
thus cause a crash on dereference on some host architectures). Newer
5
indeed valid filenames -- for nvme, they are not, as a device address is
6
versions of clang warn about this. Avoid the bug by not using the
6
still required.
7
"modify in place" byte swapping functions.
8
7
9
There are a few places where the in-place swap function is
8
The correct implementation should generate a filename of the form
10
used on something other than a packed struct field; we convert
9
"nvme://[PCI address]/[namespace]" (as the comment above
11
those anyway, for consistency.
10
nvme_parse_filename() describes).
12
11
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Alberto Garcia <berto@igalia.com>
14
Message-id: 20190201192935.18394-27-mreitz@redhat.com
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/nvme.c | 23 +++++++++--------------
18
1 file changed, 9 insertions(+), 14 deletions(-)
14
19
15
There are other places where we take the address of a packed member
20
diff --git a/block/nvme.c b/block/nvme.c
16
in this file for other purposes than passing it to a byteswap
17
function (all the calls to qemu_uuid_*()); we leave those for now.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/vdi.c | 64 ++++++++++++++++++++++++++---------------------------
24
1 file changed, 32 insertions(+), 32 deletions(-)
25
26
diff --git a/block/vdi.c b/block/vdi.c
27
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
28
--- a/block/vdi.c
22
--- a/block/nvme.c
29
+++ b/block/vdi.c
23
+++ b/block/nvme.c
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
25
32
static void vdi_header_to_cpu(VdiHeader *header)
26
/* Total size of mapped qiov, accessed under dma_map_lock */
27
int dma_map_count;
28
+
29
+ /* PCI address (required for nvme_refresh_filename()) */
30
+ char *device;
31
} BDRVNVMeState;
32
33
#define NVME_BLOCK_OPT_DEVICE "device"
34
@@ -XXX,XX +XXX,XX @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace,
35
36
qemu_co_mutex_init(&s->dma_map_lock);
37
qemu_co_queue_init(&s->dma_flush_queue);
38
+ s->device = g_strdup(device);
39
s->nsid = namespace;
40
s->aio_context = bdrv_get_aio_context(bs);
41
ret = event_notifier_init(&s->irq_notifier, 0);
42
@@ -XXX,XX +XXX,XX @@ static void nvme_close(BlockDriverState *bs)
43
event_notifier_cleanup(&s->irq_notifier);
44
qemu_vfio_pci_unmap_bar(s->vfio, 0, (void *)s->regs, 0, NVME_BAR_SIZE);
45
qemu_vfio_close(s->vfio);
46
+
47
+ g_free(s->device);
48
}
49
50
static int nvme_file_open(BlockDriverState *bs, QDict *options, int flags,
51
@@ -XXX,XX +XXX,XX @@ static int nvme_reopen_prepare(BDRVReopenState *reopen_state,
52
53
static void nvme_refresh_filename(BlockDriverState *bs)
33
{
54
{
34
- le32_to_cpus(&header->signature);
55
- const QDictEntry *e;
35
- le32_to_cpus(&header->version);
56
-
36
- le32_to_cpus(&header->header_size);
57
- for (e = qdict_first(bs->full_open_options); e;
37
- le32_to_cpus(&header->image_type);
58
- e = qdict_next(bs->full_open_options, e))
38
- le32_to_cpus(&header->image_flags);
59
- {
39
- le32_to_cpus(&header->offset_bmap);
60
- /* These options can be ignored */
40
- le32_to_cpus(&header->offset_data);
61
- if (strcmp(qdict_entry_key(e), "filename") &&
41
- le32_to_cpus(&header->cylinders);
62
- strcmp(qdict_entry_key(e), "driver"))
42
- le32_to_cpus(&header->heads);
63
- {
43
- le32_to_cpus(&header->sectors);
64
- return;
44
- le32_to_cpus(&header->sector_size);
65
- }
45
- le64_to_cpus(&header->disk_size);
66
- }
46
- le32_to_cpus(&header->block_size);
67
+ BDRVNVMeState *s = bs->opaque;
47
- le32_to_cpus(&header->block_extra);
68
48
- le32_to_cpus(&header->blocks_in_image);
69
- snprintf(bs->exact_filename, sizeof(bs->exact_filename), "%s://",
49
- le32_to_cpus(&header->blocks_allocated);
70
- bs->drv->format_name);
50
+ header->signature = le32_to_cpu(header->signature);
71
+ snprintf(bs->exact_filename, sizeof(bs->exact_filename), "nvme://%s/%i",
51
+ header->version = le32_to_cpu(header->version);
72
+ s->device, s->nsid);
52
+ header->header_size = le32_to_cpu(header->header_size);
73
}
53
+ header->image_type = le32_to_cpu(header->image_type);
74
54
+ header->image_flags = le32_to_cpu(header->image_flags);
75
static void nvme_refresh_limits(BlockDriverState *bs, Error **errp)
55
+ header->offset_bmap = le32_to_cpu(header->offset_bmap);
56
+ header->offset_data = le32_to_cpu(header->offset_data);
57
+ header->cylinders = le32_to_cpu(header->cylinders);
58
+ header->heads = le32_to_cpu(header->heads);
59
+ header->sectors = le32_to_cpu(header->sectors);
60
+ header->sector_size = le32_to_cpu(header->sector_size);
61
+ header->disk_size = le64_to_cpu(header->disk_size);
62
+ header->block_size = le32_to_cpu(header->block_size);
63
+ header->block_extra = le32_to_cpu(header->block_extra);
64
+ header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
65
+ header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
66
qemu_uuid_bswap(&header->uuid_image);
67
qemu_uuid_bswap(&header->uuid_last_snap);
68
qemu_uuid_bswap(&header->uuid_link);
69
@@ -XXX,XX +XXX,XX @@ static void vdi_header_to_cpu(VdiHeader *header)
70
71
static void vdi_header_to_le(VdiHeader *header)
72
{
73
- cpu_to_le32s(&header->signature);
74
- cpu_to_le32s(&header->version);
75
- cpu_to_le32s(&header->header_size);
76
- cpu_to_le32s(&header->image_type);
77
- cpu_to_le32s(&header->image_flags);
78
- cpu_to_le32s(&header->offset_bmap);
79
- cpu_to_le32s(&header->offset_data);
80
- cpu_to_le32s(&header->cylinders);
81
- cpu_to_le32s(&header->heads);
82
- cpu_to_le32s(&header->sectors);
83
- cpu_to_le32s(&header->sector_size);
84
- cpu_to_le64s(&header->disk_size);
85
- cpu_to_le32s(&header->block_size);
86
- cpu_to_le32s(&header->block_extra);
87
- cpu_to_le32s(&header->blocks_in_image);
88
- cpu_to_le32s(&header->blocks_allocated);
89
+ header->signature = cpu_to_le32(header->signature);
90
+ header->version = cpu_to_le32(header->version);
91
+ header->header_size = cpu_to_le32(header->header_size);
92
+ header->image_type = cpu_to_le32(header->image_type);
93
+ header->image_flags = cpu_to_le32(header->image_flags);
94
+ header->offset_bmap = cpu_to_le32(header->offset_bmap);
95
+ header->offset_data = cpu_to_le32(header->offset_data);
96
+ header->cylinders = cpu_to_le32(header->cylinders);
97
+ header->heads = cpu_to_le32(header->heads);
98
+ header->sectors = cpu_to_le32(header->sectors);
99
+ header->sector_size = cpu_to_le32(header->sector_size);
100
+ header->disk_size = cpu_to_le64(header->disk_size);
101
+ header->block_size = cpu_to_le32(header->block_size);
102
+ header->block_extra = cpu_to_le32(header->block_extra);
103
+ header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
104
+ header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
105
qemu_uuid_bswap(&header->uuid_image);
106
qemu_uuid_bswap(&header->uuid_last_snap);
107
qemu_uuid_bswap(&header->uuid_link);
108
--
76
--
109
2.19.1
77
2.20.1
110
78
111
79
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
Both of the defaults we currently have in the curl driver are named
4
it might not be actually aligned enough for that pointer type (and
4
based on a slightly different schema, let's unify that and call both
5
thus cause a crash on dereference on some host architectures). Newer
5
CURL_BLOCK_OPT_${NAME}_DEFAULT.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
6
9
There are a few places where the in-place swap function is
7
While at it, we can add a macro for the third option for which a default
10
used on something other than a packed struct field; we convert
8
exists, namely "sslverify".
11
those anyway, for consistency.
12
9
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20190201192935.18394-28-mreitz@redhat.com
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/curl.c | 13 ++++++++-----
16
1 file changed, 8 insertions(+), 5 deletions(-)
14
17
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
diff --git a/block/curl.c b/block/curl.c
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/vhdx.h | 12 ++---
20
block/vhdx-endian.c | 118 ++++++++++++++++++++++----------------------
21
block/vhdx-log.c | 4 +-
22
block/vhdx.c | 18 +++----
23
4 files changed, 76 insertions(+), 76 deletions(-)
24
25
diff --git a/block/vhdx.h b/block/vhdx.h
26
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
27
--- a/block/vhdx.h
20
--- a/block/curl.c
28
+++ b/block/vhdx.h
21
+++ b/block/curl.c
29
@@ -XXX,XX +XXX,XX @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
22
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
30
23
31
static inline void leguid_to_cpus(MSGUID *guid)
24
#define CURL_NUM_STATES 8
32
{
25
#define CURL_NUM_ACB 8
33
- le32_to_cpus(&guid->data1);
26
-#define READ_AHEAD_DEFAULT (256 * 1024)
34
- le16_to_cpus(&guid->data2);
27
-#define CURL_TIMEOUT_DEFAULT 5
35
- le16_to_cpus(&guid->data3);
28
#define CURL_TIMEOUT_MAX 10000
36
+ guid->data1 = le32_to_cpu(guid->data1);
29
37
+ guid->data2 = le16_to_cpu(guid->data2);
30
#define CURL_BLOCK_OPT_URL "url"
38
+ guid->data3 = le16_to_cpu(guid->data3);
31
@@ -XXX,XX +XXX,XX @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
39
}
32
#define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
40
33
#define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
41
static inline void cpu_to_leguids(MSGUID *guid)
34
42
{
35
+#define CURL_BLOCK_OPT_READAHEAD_DEFAULT (256 * 1024)
43
- cpu_to_le32s(&guid->data1);
36
+#define CURL_BLOCK_OPT_SSLVERIFY_DEFAULT true
44
- cpu_to_le16s(&guid->data2);
37
+#define CURL_BLOCK_OPT_TIMEOUT_DEFAULT 5
45
- cpu_to_le16s(&guid->data3);
38
+
46
+ guid->data1 = cpu_to_le32(guid->data1);
39
struct BDRVCURLState;
47
+ guid->data2 = cpu_to_le16(guid->data2);
40
48
+ guid->data3 = cpu_to_le16(guid->data3);
41
static bool libcurl_initialized;
49
}
42
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
50
51
void vhdx_header_le_import(VHDXHeader *h);
52
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/vhdx-endian.c
55
+++ b/block/vhdx-endian.c
56
@@ -XXX,XX +XXX,XX @@ void vhdx_header_le_import(VHDXHeader *h)
57
{
58
assert(h != NULL);
59
60
- le32_to_cpus(&h->signature);
61
- le32_to_cpus(&h->checksum);
62
- le64_to_cpus(&h->sequence_number);
63
+ h->signature = le32_to_cpu(h->signature);
64
+ h->checksum = le32_to_cpu(h->checksum);
65
+ h->sequence_number = le64_to_cpu(h->sequence_number);
66
67
leguid_to_cpus(&h->file_write_guid);
68
leguid_to_cpus(&h->data_write_guid);
69
leguid_to_cpus(&h->log_guid);
70
71
- le16_to_cpus(&h->log_version);
72
- le16_to_cpus(&h->version);
73
- le32_to_cpus(&h->log_length);
74
- le64_to_cpus(&h->log_offset);
75
+ h->log_version = le16_to_cpu(h->log_version);
76
+ h->version = le16_to_cpu(h->version);
77
+ h->log_length = le32_to_cpu(h->log_length);
78
+ h->log_offset = le64_to_cpu(h->log_offset);
79
}
80
81
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
82
@@ -XXX,XX +XXX,XX @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
83
{
84
assert(d != NULL);
85
86
- le32_to_cpus(&d->signature);
87
- le64_to_cpus(&d->file_offset);
88
- le64_to_cpus(&d->sequence_number);
89
+ d->signature = le32_to_cpu(d->signature);
90
+ d->file_offset = le64_to_cpu(d->file_offset);
91
+ d->sequence_number = le64_to_cpu(d->sequence_number);
92
}
93
94
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
95
{
96
assert(d != NULL);
97
98
- cpu_to_le32s(&d->signature);
99
- cpu_to_le32s(&d->trailing_bytes);
100
- cpu_to_le64s(&d->leading_bytes);
101
- cpu_to_le64s(&d->file_offset);
102
- cpu_to_le64s(&d->sequence_number);
103
+ d->signature = cpu_to_le32(d->signature);
104
+ d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
105
+ d->leading_bytes = cpu_to_le64(d->leading_bytes);
106
+ d->file_offset = cpu_to_le64(d->file_offset);
107
+ d->sequence_number = cpu_to_le64(d->sequence_number);
108
}
109
110
void vhdx_log_data_le_import(VHDXLogDataSector *d)
111
{
112
assert(d != NULL);
113
114
- le32_to_cpus(&d->data_signature);
115
- le32_to_cpus(&d->sequence_high);
116
- le32_to_cpus(&d->sequence_low);
117
+ d->data_signature = le32_to_cpu(d->data_signature);
118
+ d->sequence_high = le32_to_cpu(d->sequence_high);
119
+ d->sequence_low = le32_to_cpu(d->sequence_low);
120
}
121
122
void vhdx_log_data_le_export(VHDXLogDataSector *d)
123
{
124
assert(d != NULL);
125
126
- cpu_to_le32s(&d->data_signature);
127
- cpu_to_le32s(&d->sequence_high);
128
- cpu_to_le32s(&d->sequence_low);
129
+ d->data_signature = cpu_to_le32(d->data_signature);
130
+ d->sequence_high = cpu_to_le32(d->sequence_high);
131
+ d->sequence_low = cpu_to_le32(d->sequence_low);
132
}
133
134
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
135
{
136
assert(hdr != NULL);
137
138
- le32_to_cpus(&hdr->signature);
139
- le32_to_cpus(&hdr->checksum);
140
- le32_to_cpus(&hdr->entry_length);
141
- le32_to_cpus(&hdr->tail);
142
- le64_to_cpus(&hdr->sequence_number);
143
- le32_to_cpus(&hdr->descriptor_count);
144
+ hdr->signature = le32_to_cpu(hdr->signature);
145
+ hdr->checksum = le32_to_cpu(hdr->checksum);
146
+ hdr->entry_length = le32_to_cpu(hdr->entry_length);
147
+ hdr->tail = le32_to_cpu(hdr->tail);
148
+ hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
149
+ hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
150
leguid_to_cpus(&hdr->log_guid);
151
- le64_to_cpus(&hdr->flushed_file_offset);
152
- le64_to_cpus(&hdr->last_file_offset);
153
+ hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
154
+ hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
155
}
156
157
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
158
{
159
assert(hdr != NULL);
160
161
- cpu_to_le32s(&hdr->signature);
162
- cpu_to_le32s(&hdr->checksum);
163
- cpu_to_le32s(&hdr->entry_length);
164
- cpu_to_le32s(&hdr->tail);
165
- cpu_to_le64s(&hdr->sequence_number);
166
- cpu_to_le32s(&hdr->descriptor_count);
167
+ hdr->signature = cpu_to_le32(hdr->signature);
168
+ hdr->checksum = cpu_to_le32(hdr->checksum);
169
+ hdr->entry_length = cpu_to_le32(hdr->entry_length);
170
+ hdr->tail = cpu_to_le32(hdr->tail);
171
+ hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
172
+ hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
173
cpu_to_leguids(&hdr->log_guid);
174
- cpu_to_le64s(&hdr->flushed_file_offset);
175
- cpu_to_le64s(&hdr->last_file_offset);
176
+ hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
177
+ hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
178
}
179
180
181
@@ -XXX,XX +XXX,XX @@ void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
182
{
183
assert(hdr != NULL);
184
185
- le32_to_cpus(&hdr->signature);
186
- le32_to_cpus(&hdr->checksum);
187
- le32_to_cpus(&hdr->entry_count);
188
+ hdr->signature = le32_to_cpu(hdr->signature);
189
+ hdr->checksum = le32_to_cpu(hdr->checksum);
190
+ hdr->entry_count = le32_to_cpu(hdr->entry_count);
191
}
192
193
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
194
{
195
assert(hdr != NULL);
196
197
- cpu_to_le32s(&hdr->signature);
198
- cpu_to_le32s(&hdr->checksum);
199
- cpu_to_le32s(&hdr->entry_count);
200
+ hdr->signature = cpu_to_le32(hdr->signature);
201
+ hdr->checksum = cpu_to_le32(hdr->checksum);
202
+ hdr->entry_count = cpu_to_le32(hdr->entry_count);
203
}
204
205
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
206
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
207
assert(e != NULL);
208
209
leguid_to_cpus(&e->guid);
210
- le64_to_cpus(&e->file_offset);
211
- le32_to_cpus(&e->length);
212
- le32_to_cpus(&e->data_bits);
213
+ e->file_offset = le64_to_cpu(e->file_offset);
214
+ e->length = le32_to_cpu(e->length);
215
+ e->data_bits = le32_to_cpu(e->data_bits);
216
}
217
218
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
219
@@ -XXX,XX +XXX,XX @@ void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
220
assert(e != NULL);
221
222
cpu_to_leguids(&e->guid);
223
- cpu_to_le64s(&e->file_offset);
224
- cpu_to_le32s(&e->length);
225
- cpu_to_le32s(&e->data_bits);
226
+ e->file_offset = cpu_to_le64(e->file_offset);
227
+ e->length = cpu_to_le32(e->length);
228
+ e->data_bits = cpu_to_le32(e->data_bits);
229
}
230
231
232
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
233
{
234
assert(hdr != NULL);
235
236
- le64_to_cpus(&hdr->signature);
237
- le16_to_cpus(&hdr->entry_count);
238
+ hdr->signature = le64_to_cpu(hdr->signature);
239
+ hdr->entry_count = le16_to_cpu(hdr->entry_count);
240
}
241
242
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
243
{
244
assert(hdr != NULL);
245
246
- cpu_to_le64s(&hdr->signature);
247
- cpu_to_le16s(&hdr->entry_count);
248
+ hdr->signature = cpu_to_le64(hdr->signature);
249
+ hdr->entry_count = cpu_to_le16(hdr->entry_count);
250
}
251
252
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
253
@@ -XXX,XX +XXX,XX @@ void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
254
assert(e != NULL);
255
256
leguid_to_cpus(&e->item_id);
257
- le32_to_cpus(&e->offset);
258
- le32_to_cpus(&e->length);
259
- le32_to_cpus(&e->data_bits);
260
+ e->offset = le32_to_cpu(e->offset);
261
+ e->length = le32_to_cpu(e->length);
262
+ e->data_bits = le32_to_cpu(e->data_bits);
263
}
264
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
265
{
266
assert(e != NULL);
267
268
cpu_to_leguids(&e->item_id);
269
- cpu_to_le32s(&e->offset);
270
- cpu_to_le32s(&e->length);
271
- cpu_to_le32s(&e->data_bits);
272
+ e->offset = cpu_to_le32(e->offset);
273
+ e->length = cpu_to_le32(e->length);
274
+ e->data_bits = cpu_to_le32(e->data_bits);
275
}
276
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
277
index XXXXXXX..XXXXXXX 100644
278
--- a/block/vhdx-log.c
279
+++ b/block/vhdx-log.c
280
@@ -XXX,XX +XXX,XX @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
281
/* 8 + 4084 + 4 = 4096, 1 log sector */
282
memcpy(&desc->leading_bytes, data, 8);
283
data += 8;
284
- cpu_to_le64s(&desc->leading_bytes);
285
+ desc->leading_bytes = cpu_to_le64(desc->leading_bytes);
286
memcpy(sector->data, data, 4084);
287
data += 4084;
288
memcpy(&desc->trailing_bytes, data, 4);
289
- cpu_to_le32s(&desc->trailing_bytes);
290
+ desc->trailing_bytes = cpu_to_le32(desc->trailing_bytes);
291
data += 4;
292
293
sector->sequence_high = (uint32_t) (seq >> 32);
294
diff --git a/block/vhdx.c b/block/vhdx.c
295
index XXXXXXX..XXXXXXX 100644
296
--- a/block/vhdx.c
297
+++ b/block/vhdx.c
298
@@ -XXX,XX +XXX,XX @@ uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
299
300
memset(buf + crc_offset, 0, sizeof(crc));
301
crc = crc32c(0xffffffff, buf, size);
302
- cpu_to_le32s(&crc);
303
+ crc = cpu_to_le32(crc);
304
memcpy(buf + crc_offset, &crc, sizeof(crc));
305
306
return crc;
307
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
308
goto exit;
309
}
43
}
310
44
311
- le32_to_cpus(&s->params.block_size);
45
s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
312
- le32_to_cpus(&s->params.data_bits);
46
- READ_AHEAD_DEFAULT);
313
+ s->params.block_size = le32_to_cpu(s->params.block_size);
47
+ CURL_BLOCK_OPT_READAHEAD_DEFAULT);
314
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
48
if ((s->readahead_size & 0x1ff) != 0) {
315
49
error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
316
50
s->readahead_size);
317
/* We now have the file parameters, so we can tell if this is a
51
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
319
goto exit;
320
}
52
}
321
53
322
- le64_to_cpus(&s->virtual_disk_size);
54
s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
323
- le32_to_cpus(&s->logical_sector_size);
55
- CURL_TIMEOUT_DEFAULT);
324
- le32_to_cpus(&s->physical_sector_size);
56
+ CURL_BLOCK_OPT_TIMEOUT_DEFAULT);
325
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
57
if (s->timeout > CURL_TIMEOUT_MAX) {
326
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
58
error_setg(errp, "timeout parameter is too large or negative");
327
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
59
goto out_noclean;
328
329
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
330
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
331
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
332
/* endian convert, and verify populated BAT field file offsets against
333
* region table and log entries */
334
for (i = 0; i < s->bat_entries; i++) {
335
- le64_to_cpus(&s->bat[i]);
336
+ s->bat[i] = le64_to_cpu(s->bat[i]);
337
if (payblocks--) {
338
/* payload bat entries */
339
if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
340
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_new_metadata(BlockBackend *blk,
341
mt_file_params->block_size = cpu_to_le32(block_size);
342
if (type == VHDX_TYPE_FIXED) {
343
mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
344
- cpu_to_le32s(&mt_file_params->data_bits);
345
+ mt_file_params->data_bits = cpu_to_le32(mt_file_params->data_bits);
346
}
60
}
347
61
348
vhdx_guid_generate(&mt_page83->page_83_data);
62
- s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
349
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
63
+ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY,
350
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
64
+ CURL_BLOCK_OPT_SSLVERIFY_DEFAULT);
351
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
65
352
block_state);
66
cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
353
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
67
cookie_secret = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE_SECRET);
354
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
355
sector_num += s->sectors_per_block;
356
}
357
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
358
--
68
--
359
2.19.1
69
2.20.1
360
70
361
71
diff view generated by jsdifflib
1
If read-only=off, but auto-read-only=on is given, just degrade to
1
From: Max Reitz <mreitz@redhat.com>
2
read-only.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
Message-id: 20190201192935.18394-29-mreitz@redhat.com
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
7
---
7
block/curl.c | 8 ++++----
8
block/curl.c | 21 +++++++++++++++++++++
8
1 file changed, 4 insertions(+), 4 deletions(-)
9
1 file changed, 21 insertions(+)
9
10
10
diff --git a/block/curl.c b/block/curl.c
11
diff --git a/block/curl.c b/block/curl.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/block/curl.c
13
--- a/block/curl.c
13
+++ b/block/curl.c
14
+++ b/block/curl.c
14
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
15
@@ -XXX,XX +XXX,XX @@ static int64_t curl_getlength(BlockDriverState *bs)
15
const char *protocol_delimiter;
16
return s->len;
16
int ret;
17
}
17
18
18
-
19
+static void curl_refresh_filename(BlockDriverState *bs)
19
- if (flags & BDRV_O_RDWR) {
20
+{
20
- error_setg(errp, "curl block device does not support writes");
21
+ BDRVCURLState *s = bs->opaque;
21
- return -EROFS;
22
+
22
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
23
+ /* "readahead" and "timeout" do not change the guest-visible data,
23
+ errp);
24
+ * so ignore them */
24
+ if (ret < 0) {
25
+ if (s->sslverify != CURL_BLOCK_OPT_SSLVERIFY_DEFAULT ||
25
+ return ret;
26
+ s->cookie || s->username || s->password || s->proxyusername ||
26
}
27
+ s->proxypassword)
27
28
+ {
28
if (!libcurl_initialized) {
29
+ return;
30
+ }
31
+
32
+ pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), s->url);
33
+}
34
+
35
+
36
static const char *const curl_strong_runtime_opts[] = {
37
CURL_BLOCK_OPT_URL,
38
CURL_BLOCK_OPT_SSLVERIFY,
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_http = {
40
.bdrv_detach_aio_context = curl_detach_aio_context,
41
.bdrv_attach_aio_context = curl_attach_aio_context,
42
43
+ .bdrv_refresh_filename = curl_refresh_filename,
44
.strong_runtime_opts = curl_strong_runtime_opts,
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_https = {
48
.bdrv_detach_aio_context = curl_detach_aio_context,
49
.bdrv_attach_aio_context = curl_attach_aio_context,
50
51
+ .bdrv_refresh_filename = curl_refresh_filename,
52
.strong_runtime_opts = curl_strong_runtime_opts,
53
};
54
55
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftp = {
56
.bdrv_detach_aio_context = curl_detach_aio_context,
57
.bdrv_attach_aio_context = curl_attach_aio_context,
58
59
+ .bdrv_refresh_filename = curl_refresh_filename,
60
.strong_runtime_opts = curl_strong_runtime_opts,
61
};
62
63
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ftps = {
64
.bdrv_detach_aio_context = curl_detach_aio_context,
65
.bdrv_attach_aio_context = curl_attach_aio_context,
66
67
+ .bdrv_refresh_filename = curl_refresh_filename,
68
.strong_runtime_opts = curl_strong_runtime_opts,
69
};
70
29
--
71
--
30
2.19.1
72
2.20.1
31
73
32
74
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Just like in qemu_opts_print_help(), print the object name as a caption
3
While we cannot represent the latency-ns option in a filename, it is not
4
instead of on every single line, indent all options, add angle brackets
4
a strong option so not being able to should not stop us from generating
5
around types, and align the descriptions after 24 characters.
5
a filename nonetheless.
6
7
Also, indent every object name in the list of available objects.
8
6
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20190201192935.18394-30-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
11
---
13
vl.c | 13 ++++++++++---
12
block/null.c | 3 ++-
14
1 file changed, 10 insertions(+), 3 deletions(-)
13
1 file changed, 2 insertions(+), 1 deletion(-)
15
14
16
diff --git a/vl.c b/vl.c
15
diff --git a/block/null.c b/block/null.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/vl.c
17
--- a/block/null.c
19
+++ b/vl.c
18
+++ b/block/null.c
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
19
@@ -XXX,XX +XXX,XX @@ static void null_refresh_filename(BlockDriverState *bs)
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
20
{
22
for (l = list; l != NULL; l = l->next) {
21
/* These options can be ignored */
23
ObjectClass *oc = OBJECT_CLASS(l->data);
22
if (strcmp(qdict_entry_key(e), "filename") &&
24
- printf("%s\n", object_class_get_name(oc));
23
- strcmp(qdict_entry_key(e), "driver"))
25
+ printf(" %s\n", object_class_get_name(oc));
24
+ strcmp(qdict_entry_key(e), "driver") &&
26
}
25
+ strcmp(qdict_entry_key(e), NULL_OPT_LATENCY))
27
g_slist_free(list);
26
{
28
exit(0);
27
return;
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
30
}
31
32
str = g_string_new(NULL);
33
- g_string_append_printf(str, "%s.%s=%s", type,
34
- prop->name, prop->type);
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
36
if (prop->description) {
37
+ if (str->len < 24) {
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
39
+ }
40
g_string_append_printf(str, " - %s", prop->description);
41
}
42
g_ptr_array_add(array, g_string_free(str, false));
43
}
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
45
+ if (array->len > 0) {
46
+ printf("%s options:\n", type);
47
+ } else {
48
+ printf("There are no options for %s.\n", type);
49
+ }
50
for (i = 0; i < array->len; i++) {
51
printf("%s\n", (char *)array->pdata[i]);
52
}
28
}
53
--
29
--
54
2.19.1
30
2.20.1
55
31
56
32
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
When BDSs are created by qemu itself (e.g. as filters in block jobs),
4
they may not have a "driver" option in their options QDict. When
5
generating a json:{} filename, however, it must always be present.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-id: 20190201192935.18394-31-mreitz@redhat.com
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block.c | 6 ++++++
13
1 file changed, 6 insertions(+)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
20
}
21
}
22
23
+ if (!qdict_haskey(d, "driver")) {
24
+ /* Drivers created with bdrv_new_open_driver() may not have a
25
+ * @driver option. Add it here. */
26
+ qdict_put_str(d, "driver", bs->drv->format_name);
27
+ }
28
+
29
return found_any;
30
}
31
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Message-id: 20190201192935.18394-32-mreitz@redhat.com
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/qemu-iotests/224 | 139 +++++++++++++++++++++++++++++++++++++
8
tests/qemu-iotests/224.out | 18 +++++
9
tests/qemu-iotests/group | 1 +
10
3 files changed, 158 insertions(+)
11
create mode 100755 tests/qemu-iotests/224
12
create mode 100644 tests/qemu-iotests/224.out
13
14
diff --git a/tests/qemu-iotests/224 b/tests/qemu-iotests/224
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/224
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python
21
+#
22
+# Test json:{} filenames with qemu-internal BDSs
23
+# (the one of commit, to be precise)
24
+#
25
+# Copyright (C) 2018 Red Hat, Inc.
26
+#
27
+# This program is free software; you can redistribute it and/or modify
28
+# it under the terms of the GNU General Public License as published by
29
+# the Free Software Foundation; either version 2 of the License, or
30
+# (at your option) any later version.
31
+#
32
+# This program is distributed in the hope that it will be useful,
33
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
+# GNU General Public License for more details.
36
+#
37
+# You should have received a copy of the GNU General Public License
38
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
39
+#
40
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
41
+
42
+import iotests
43
+from iotests import log, qemu_img, qemu_io_silent, filter_qmp_testfiles, \
44
+ filter_qmp_imgfmt
45
+import json
46
+
47
+# Need backing file support (for arbitrary backing formats)
48
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed'])
49
+iotests.verify_platform(['linux'])
50
+
51
+
52
+# There are two variations of this test:
53
+# (1) We do not set filter_node_name. In that case, the commit_top
54
+# driver should not appear anywhere.
55
+# (2) We do set filter_node_name. In that case, it should appear.
56
+#
57
+# This for loop executes both.
58
+for filter_node_name in False, True:
59
+ log('')
60
+ log('--- filter_node_name: %s ---' % filter_node_name)
61
+ log('')
62
+
63
+ with iotests.FilePath('base.img') as base_img_path, \
64
+ iotests.FilePath('mid.img') as mid_img_path, \
65
+ iotests.FilePath('top.img') as top_img_path, \
66
+ iotests.VM() as vm:
67
+
68
+ assert qemu_img('create', '-f', iotests.imgfmt,
69
+ base_img_path, '64M') == 0
70
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
71
+ mid_img_path) == 0
72
+ assert qemu_img('create', '-f', iotests.imgfmt, '-b', mid_img_path,
73
+ top_img_path) == 0
74
+
75
+ # Something to commit
76
+ assert qemu_io_silent(mid_img_path, '-c', 'write -P 1 0 1M') == 0
77
+
78
+ vm.launch()
79
+
80
+ # Change the bottom-most image's backing file (to null-co://)
81
+ # to enforce json:{} filenames
82
+ vm.qmp_log('blockdev-add',
83
+ node_name='top',
84
+ driver=iotests.imgfmt,
85
+ file={
86
+ 'driver': 'file',
87
+ 'filename': top_img_path
88
+ },
89
+ backing={
90
+ 'node-name': 'mid',
91
+ 'driver': iotests.imgfmt,
92
+ 'file': {
93
+ 'driver': 'file',
94
+ 'filename': mid_img_path
95
+ },
96
+ 'backing': {
97
+ 'node-name': 'base',
98
+ 'driver': iotests.imgfmt,
99
+ 'file': {
100
+ 'driver': 'file',
101
+ 'filename': base_img_path
102
+ },
103
+ 'backing': {
104
+ 'driver': 'null-co'
105
+ }
106
+ }
107
+ },
108
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
109
+
110
+ # As long as block-commit does not accept node names, we have to
111
+ # get our mid/base filenames here
112
+ mid_name = vm.node_info('mid')['image']['filename']
113
+ base_name = vm.node_info('base')['image']['filename']
114
+
115
+ assert mid_name[:5] == 'json:'
116
+ assert base_name[:5] == 'json:'
117
+
118
+ # Start the block job
119
+ if filter_node_name:
120
+ vm.qmp_log('block-commit',
121
+ job_id='commit',
122
+ device='top',
123
+ filter_node_name='filter_node',
124
+ top=mid_name,
125
+ base=base_name,
126
+ speed=1,
127
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
128
+ else:
129
+ vm.qmp_log('block-commit',
130
+ job_id='commit',
131
+ device='top',
132
+ top=mid_name,
133
+ base=base_name,
134
+ speed=1,
135
+ filters=[filter_qmp_testfiles, filter_qmp_imgfmt])
136
+
137
+ vm.qmp_log('job-pause', id='commit')
138
+
139
+ # Get and parse top's json:{} filename
140
+ top_name = vm.node_info('top')['image']['filename']
141
+
142
+ vm.shutdown()
143
+
144
+ assert top_name[:5] == 'json:'
145
+ top_options = json.loads(top_name[5:])
146
+
147
+ if filter_node_name:
148
+ # This should be present and set
149
+ assert top_options['backing']['driver'] == 'commit_top'
150
+ # And the mid image is commit_top's backing image
151
+ mid_options = top_options['backing']['backing']
152
+ else:
153
+ # The mid image should appear as the immediate backing BDS
154
+ # of top
155
+ mid_options = top_options['backing']
156
+
157
+ assert mid_options['driver'] == iotests.imgfmt
158
+ assert mid_options['file']['filename'] == mid_img_path
159
diff --git a/tests/qemu-iotests/224.out b/tests/qemu-iotests/224.out
160
new file mode 100644
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/tests/qemu-iotests/224.out
164
@@ -XXX,XX +XXX,XX @@
165
+
166
+--- filter_node_name: False ---
167
+
168
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
169
+{"return": {}}
170
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
171
+{"return": {}}
172
+{"execute": "job-pause", "arguments": {"id": "commit"}}
173
+{"return": {}}
174
+
175
+--- filter_node_name: True ---
176
+
177
+{"execute": "blockdev-add", "arguments": {"backing": {"backing": {"backing": {"driver": "null-co"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-base.img"}, "node-name": "base"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-mid.img"}, "node-name": "mid"}, "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top.img"}, "node-name": "top"}}
178
+{"return": {}}
179
+{"execute": "block-commit", "arguments": {"base": "json:{\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}", "device": "top", "filter-node-name": "filter_node", "job-id": "commit", "speed": 1, "top": "json:{\"backing\": {\"backing\": {\"driver\": \"null-co\"}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-base.img\"}}, \"driver\": \"IMGFMT\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/PID-mid.img\"}}"}}
180
+{"return": {}}
181
+{"execute": "job-pause", "arguments": {"id": "commit"}}
182
+{"return": {}}
183
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
184
index XXXXXXX..XXXXXXX 100644
185
--- a/tests/qemu-iotests/group
186
+++ b/tests/qemu-iotests/group
187
@@ -XXX,XX +XXX,XX @@
188
221 rw auto quick
189
222 rw auto quick
190
223 rw auto quick
191
+224 rw auto quick
192
225 rw auto quick
193
226 auto quick
194
227 auto quick
195
--
196
2.20.1
197
198
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
There is no good reason why there should be a newline in this
3
math.ceil() returns an integer on Python 3.x, but a float on Python 2.x.
4
description, so remove it.
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.
5
10
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
14
Message-id: 20190210145736.1486-3-mreitz@redhat.com
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
16
---
11
vl.c | 2 +-
17
tests/qemu-iotests/237 | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 1 insertion(+), 1 deletion(-)
13
19
14
diff --git a/vl.c b/vl.c
20
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100755
16
--- a/vl.c
22
--- a/tests/qemu-iotests/237
17
+++ b/vl.c
23
+++ b/tests/qemu-iotests/237
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.vmdk') as disk_path, \
19
}, {
25
iotests.log("= %s %d =" % (subfmt, size))
20
.name = "file",
26
iotests.log("")
21
.type = QEMU_OPT_STRING,
27
22
- .help = "Sets the name of the file from which\n"
28
- num_extents = math.ceil(size / 2.0**31)
23
+ .help = "Sets the name of the file from which "
29
+ num_extents = int(math.ceil(size / 2.0**31))
24
"the fw_cfg blob will be loaded",
30
extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
25
}, {
31
26
.name = "string",
32
vm.launch()
27
--
33
--
28
2.19.1
34
2.20.1
29
35
30
36
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
This test creates no such file.
4
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
Message-id: 20190210145736.1486-4-mreitz@redhat.com
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/232 | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/232
17
+++ b/tests/qemu-iotests/232
18
@@ -XXX,XX +XXX,XX @@ status=1    # failure is the default!
19
_cleanup()
20
{
21
_cleanup_test_img
22
- rm -f $TEST_IMG.snap
23
}
24
trap "_cleanup; exit \$status" 0 1 2 3 15
25
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
Following the example of qemu_opts_print_help(), indent all entries in
3
filter_qmp_testfiles() currently filters the filename only for specific
4
the list of character devices.
4
keys. However, there are more keys that take filenames (such as
5
block-commit's @top and @base, or ssh's @path), and it does not make
6
sense to list them all here. "$TEST_DIR/$PID-" should have enough
7
entropy not to appear anywhere randomly.
5
8
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Message-id: 20190210145736.1486-8-mreitz@redhat.com
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
13
---
10
chardev/char.c | 2 +-
14
tests/qemu-iotests/iotests.py | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
16
13
diff --git a/chardev/char.c b/chardev/char.c
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/chardev/char.c
19
--- a/tests/qemu-iotests/iotests.py
16
+++ b/chardev/char.c
20
+++ b/tests/qemu-iotests/iotests.py
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
21
@@ -XXX,XX +XXX,XX @@ def filter_testfiles(msg):
18
{
22
19
GString *str = opaque;
23
def filter_qmp_testfiles(qmsg):
20
24
def _filter(key, value):
21
- g_string_append_printf(str, "\n%s", name);
25
- if key == 'filename' or key == 'backing-file':
22
+ g_string_append_printf(str, "\n %s", name);
26
+ if is_str(value):
23
}
27
return filter_testfiles(value)
24
28
return value
25
static const char *chardev_alias_translate(const char *name)
29
return filter_qmp(qmsg, _filter)
26
--
30
--
27
2.19.1
31
2.20.1
28
32
29
33
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
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
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
This follows what qmp() does, so the output will correspond to the
4
actual QMP command.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20190210145736.1486-11-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/206.out | 56 +++++++++++++++++------------------
11
tests/qemu-iotests/207.out | 18 +++++------
12
tests/qemu-iotests/210.out | 28 +++++++++---------
13
tests/qemu-iotests/211.out | 26 ++++++++--------
14
tests/qemu-iotests/212.out | 44 +++++++++++++--------------
15
tests/qemu-iotests/213.out | 46 ++++++++++++++--------------
16
tests/qemu-iotests/237.out | 54 ++++++++++++++++-----------------
17
tests/qemu-iotests/iotests.py | 6 ++--
18
8 files changed, 140 insertions(+), 138 deletions(-)
19
20
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qemu-iotests/206.out
23
+++ b/tests/qemu-iotests/206.out
24
@@ -XXX,XX +XXX,XX @@
25
=== Successful image creation (defaults) ===
26
27
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
28
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
29
{"return": {}}
30
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
31
{"return": {}}
32
33
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}}
34
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node-name": "imgfile"}}
35
{"return": {}}
36
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
37
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}}
38
{"return": {}}
39
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
40
{"return": {}}
41
@@ -XXX,XX +XXX,XX @@ Format specific information:
42
43
=== Successful image creation (inline blockdev-add, explicit defaults) ===
44
45
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
46
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}}
47
{"return": {}}
48
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
49
{"return": {}}
50
51
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
52
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}}
53
{"return": {}}
54
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
55
{"return": {}}
56
@@ -XXX,XX +XXX,XX @@ Format specific information:
57
58
=== Successful image creation (v3 non-default options) ===
59
60
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
61
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}}
62
{"return": {}}
63
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
64
{"return": {}}
65
66
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
67
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}}
68
{"return": {}}
69
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
70
{"return": {}}
71
@@ -XXX,XX +XXX,XX @@ Format specific information:
72
73
=== Successful image creation (v2 non-default options) ===
74
75
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
76
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}}
77
{"return": {}}
78
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
79
{"return": {}}
80
81
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
82
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}}
83
{"return": {}}
84
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
85
{"return": {}}
86
@@ -XXX,XX +XXX,XX @@ Format specific information:
87
88
=== Successful image creation (encrypted) ===
89
90
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
91
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}}
92
{"return": {}}
93
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
94
{"return": {}}
95
@@ -XXX,XX +XXX,XX @@ Format specific information:
96
97
=== Invalid BlockdevRef ===
98
99
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
100
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}}
101
{"return": {}}
102
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
103
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
104
{"return": {}}
105
106
=== Invalid sizes ===
107
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
108
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}}
109
{"return": {}}
110
Job failed: Image size must be a multiple of 512 bytes
111
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
112
{"return": {}}
113
114
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
115
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}}
116
{"return": {}}
117
Job failed: Could not resize image: Image size cannot be negative
118
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
119
{"return": {}}
120
121
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
122
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}}
123
{"return": {}}
124
Job failed: Could not resize image: Image size cannot be negative
125
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
126
{"return": {}}
127
128
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
129
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}}
130
{"return": {}}
131
Job failed: Could not resize image: Failed to grow the L1 table: File too large
132
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
133
{"return": {}}
134
135
=== Invalid version ===
136
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
137
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}}
138
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
139
140
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
141
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}}
142
{"return": {}}
143
Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
144
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
145
{"return": {}}
146
147
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
148
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}}
149
{"return": {}}
150
Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
151
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
152
{"return": {}}
153
154
=== Invalid backing file options ===
155
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
156
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
157
{"return": {}}
158
Job failed: Backing file and preallocation cannot be used at the same time
159
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
160
{"return": {}}
161
162
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
163
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}}
164
{"return": {}}
165
Job failed: Backing format cannot be used without backing file
166
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
167
{"return": {}}
168
169
=== Invalid cluster size ===
170
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
171
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}}
172
{"return": {}}
173
Job failed: Cluster size must be a power of two between 512 and 2048k
174
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
175
{"return": {}}
176
177
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
178
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}}
179
{"return": {}}
180
Job failed: Cluster size must be a power of two between 512 and 2048k
181
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
182
{"return": {}}
183
184
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
185
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}}
186
{"return": {}}
187
Job failed: Cluster size must be a power of two between 512 and 2048k
188
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
189
{"return": {}}
190
191
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
192
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}}
193
{"return": {}}
194
Job failed: Cluster size must be a power of two between 512 and 2048k
195
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
196
{"return": {}}
197
198
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
199
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}}
200
{"return": {}}
201
Job failed: Could not resize image: Failed to grow the L1 table: File too large
202
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
203
{"return": {}}
204
205
=== Invalid refcount width ===
206
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
207
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}}
208
{"return": {}}
209
Job failed: Refcount width must be a power of two and may not exceed 64 bits
210
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
211
{"return": {}}
212
213
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
214
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}}
215
{"return": {}}
216
Job failed: Refcount width must be a power of two and may not exceed 64 bits
217
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
218
{"return": {}}
219
220
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
221
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}}
222
{"return": {}}
223
Job failed: Refcount width must be a power of two and may not exceed 64 bits
224
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
225
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
226
index XXXXXXX..XXXXXXX 100644
227
--- a/tests/qemu-iotests/207.out
228
+++ b/tests/qemu-iotests/207.out
229
@@ -XXX,XX +XXX,XX @@
230
=== Successful image creation (defaults) ===
231
232
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
233
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
234
{"return": {}}
235
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
236
{"return": {}}
237
@@ -XXX,XX +XXX,XX @@ virtual size: 4.0M (4194304 bytes)
238
239
=== Test host-key-check options ===
240
241
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
242
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
243
{"return": {}}
244
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
245
{"return": {}}
246
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
247
file format: IMGFMT
248
virtual size: 8.0M (8388608 bytes)
249
250
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
251
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
252
{"return": {}}
253
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
254
{"return": {}}
255
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
256
file format: IMGFMT
257
virtual size: 4.0M (4194304 bytes)
258
259
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
260
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
261
{"return": {}}
262
Job failed: remote host key does not match host_key_check 'wrong'
263
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
264
{"return": {}}
265
266
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
267
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}}
268
{"return": {}}
269
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
270
{"return": {}}
271
@@ -XXX,XX +XXX,XX @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
272
file format: IMGFMT
273
virtual size: 8.0M (8388608 bytes)
274
275
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
276
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}}
277
{"return": {}}
278
Job failed: remote host key does not match host_key_check 'wrong'
279
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
280
{"return": {}}
281
282
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
283
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "HASH", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
284
{"return": {}}
285
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
286
{"return": {}}
287
@@ -XXX,XX +XXX,XX @@ virtual size: 4.0M (4194304 bytes)
288
289
=== Invalid path and user ===
290
291
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
292
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}}
293
{"return": {}}
294
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
295
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
296
{"return": {}}
297
298
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
299
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}}
300
{"return": {}}
301
Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
302
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
303
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
304
index XXXXXXX..XXXXXXX 100644
305
--- a/tests/qemu-iotests/210.out
306
+++ b/tests/qemu-iotests/210.out
307
@@ -XXX,XX +XXX,XX @@
308
=== Successful image creation (defaults) ===
309
310
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
311
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
312
{"return": {}}
313
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
314
{"return": {}}
315
316
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}}
317
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node-name": "imgfile"}}
318
{"return": {}}
319
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
320
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}}
321
{"return": {}}
322
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
323
{"return": {}}
324
@@ -XXX,XX +XXX,XX @@ Format specific information:
325
326
=== Successful image creation (with non-default options) ===
327
328
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
329
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}}
330
{"return": {}}
331
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
332
{"return": {}}
333
334
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
335
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}}
336
{"return": {}}
337
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
338
{"return": {}}
339
@@ -XXX,XX +XXX,XX @@ Format specific information:
340
341
=== Invalid BlockdevRef ===
342
343
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
344
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}}
345
{"return": {}}
346
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
347
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
348
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
349
350
=== Zero size ===
351
352
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
353
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}}
354
{"return": {}}
355
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
356
{"return": {}}
357
@@ -XXX,XX +XXX,XX @@ Format specific information:
358
359
=== Invalid sizes ===
360
361
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
362
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}}
363
{"return": {}}
364
Job failed: The requested file size is too large
365
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
366
{"return": {}}
367
368
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
369
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}}
370
{"return": {}}
371
Job failed: The requested file size is too large
372
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
373
{"return": {}}
374
375
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
376
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}}
377
{"return": {}}
378
Job failed: The requested file size is too large
379
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
380
@@ -XXX,XX +XXX,XX @@ Job failed: The requested file size is too large
381
382
=== Resize image with invalid sizes ===
383
384
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}}
385
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775296}}
386
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
387
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}}
388
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 9223372036854775808}}
389
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
390
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}}
391
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": 18446744073709551104}}
392
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
393
-{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}}
394
+{"execute": "block_resize", "arguments": {"node-name": "node1", "size": -9223372036854775808}}
395
{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}}
396
image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
397
file format: IMGFMT
398
diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
399
index XXXXXXX..XXXXXXX 100644
400
--- a/tests/qemu-iotests/211.out
401
+++ b/tests/qemu-iotests/211.out
402
@@ -XXX,XX +XXX,XX @@
403
=== Successful image creation (defaults) ===
404
405
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
406
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
407
{"return": {}}
408
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
409
{"return": {}}
410
411
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}}
412
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node-name": "imgfile"}}
413
{"return": {}}
414
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
415
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}}
416
{"return": {}}
417
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
418
{"return": {}}
419
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
420
421
=== Successful image creation (explicit defaults) ===
422
423
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
424
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
425
{"return": {}}
426
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
427
{"return": {}}
428
429
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
430
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}}
431
{"return": {}}
432
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
433
{"return": {}}
434
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
435
436
=== Successful image creation (with non-default options) ===
437
438
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
439
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}}
440
{"return": {}}
441
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
442
{"return": {}}
443
444
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
445
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}}
446
{"return": {}}
447
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
448
{"return": {}}
449
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
450
451
=== Invalid BlockdevRef ===
452
453
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
454
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}}
455
{"return": {}}
456
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
457
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
458
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
459
460
=== Zero size ===
461
462
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
463
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}}
464
{"return": {}}
465
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
466
{"return": {}}
467
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
468
469
=== Maximum size ===
470
471
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
472
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}}
473
{"return": {}}
474
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
475
{"return": {}}
476
@@ -XXX,XX +XXX,XX @@ cluster_size: 1048576
477
478
=== Invalid sizes ===
479
480
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
481
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}}
482
{"return": {}}
483
Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
484
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
485
{"return": {}}
486
487
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
488
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}}
489
{"return": {}}
490
Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)
491
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
492
{"return": {}}
493
494
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
495
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}}
496
{"return": {}}
497
Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)
498
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
499
diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
500
index XXXXXXX..XXXXXXX 100644
501
--- a/tests/qemu-iotests/212.out
502
+++ b/tests/qemu-iotests/212.out
503
@@ -XXX,XX +XXX,XX @@
504
=== Successful image creation (defaults) ===
505
506
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
507
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
508
{"return": {}}
509
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
510
{"return": {}}
511
512
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}}
513
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node-name": "imgfile"}}
514
{"return": {}}
515
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
516
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}}
517
{"return": {}}
518
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
519
{"return": {}}
520
@@ -XXX,XX +XXX,XX @@ virtual size: 128M (134217728 bytes)
521
522
=== Successful image creation (explicit defaults) ===
523
524
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
525
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
526
{"return": {}}
527
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
528
{"return": {}}
529
530
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
531
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}}
532
{"return": {}}
533
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
534
{"return": {}}
535
@@ -XXX,XX +XXX,XX @@ virtual size: 64M (67108864 bytes)
536
537
=== Successful image creation (with non-default options) ===
538
539
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
540
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}}
541
{"return": {}}
542
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
543
{"return": {}}
544
545
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
546
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}}
547
{"return": {}}
548
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
549
{"return": {}}
550
@@ -XXX,XX +XXX,XX @@ virtual size: 32M (33554432 bytes)
551
552
=== Invalid BlockdevRef ===
553
554
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
555
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}}
556
{"return": {}}
557
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
558
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
559
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
560
561
=== Zero size ===
562
563
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
564
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}}
565
{"return": {}}
566
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
567
{"return": {}}
568
@@ -XXX,XX +XXX,XX @@ virtual size: 0 (0 bytes)
569
570
=== Maximum size ===
571
572
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
573
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}}
574
{"return": {}}
575
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
576
{"return": {}}
577
@@ -XXX,XX +XXX,XX @@ virtual size: 4096T (4503599627369984 bytes)
578
579
=== Invalid sizes ===
580
581
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
582
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}}
583
{"return": {}}
584
Job failed: Image size must be a multiple of 512 bytes
585
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
586
{"return": {}}
587
588
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
589
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}}
590
{"return": {}}
591
Job failed: Image size is too large for this cluster size
592
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
593
{"return": {}}
594
595
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
596
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}}
597
{"return": {}}
598
Job failed: Image size is too large for this cluster size
599
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
600
{"return": {}}
601
602
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
603
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}}
604
{"return": {}}
605
Job failed: Image size is too large for this cluster size
606
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
607
{"return": {}}
608
609
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
610
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}}
611
{"return": {}}
612
Job failed: Image size is too large for this cluster size
613
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
614
@@ -XXX,XX +XXX,XX @@ Job failed: Image size is too large for this cluster size
615
616
=== Invalid cluster size ===
617
618
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
619
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}}
620
{"return": {}}
621
Job failed: Cluster size must be a multiple of 512 bytes
622
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
623
{"return": {}}
624
625
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
626
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}}
627
{"return": {}}
628
Job failed: Cluster size must be a multiple of 512 bytes
629
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
630
{"return": {}}
631
632
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
633
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}}
634
{"return": {}}
635
Job failed: Cluster size is too large
636
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
637
{"return": {}}
638
639
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
640
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}}
641
{"return": {}}
642
Job failed: Cluster size is too large
643
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
644
{"return": {}}
645
646
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
647
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}}
648
{"return": {}}
649
Job failed: Cluster size is too large
650
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
651
{"return": {}}
652
653
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
654
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}}
655
{"return": {}}
656
Job failed: Image size is too large for this cluster size
657
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
658
{"return": {}}
659
660
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
661
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}}
662
{"return": {}}
663
Job failed: Image size is too large for this cluster size
664
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
665
diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
666
index XXXXXXX..XXXXXXX 100644
667
--- a/tests/qemu-iotests/213.out
668
+++ b/tests/qemu-iotests/213.out
669
@@ -XXX,XX +XXX,XX @@
670
=== Successful image creation (defaults) ===
671
672
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
673
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
674
{"return": {}}
675
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
676
{"return": {}}
677
678
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}}
679
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node-name": "imgfile"}}
680
{"return": {}}
681
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
682
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}}
683
{"return": {}}
684
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
685
{"return": {}}
686
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
687
688
=== Successful image creation (explicit defaults) ===
689
690
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
691
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
692
{"return": {}}
693
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
694
{"return": {}}
695
696
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
697
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}}
698
{"return": {}}
699
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
700
{"return": {}}
701
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
702
703
=== Successful image creation (with non-default options) ===
704
705
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
706
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}}
707
{"return": {}}
708
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
709
{"return": {}}
710
711
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
712
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}}
713
{"return": {}}
714
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
715
{"return": {}}
716
@@ -XXX,XX +XXX,XX @@ cluster_size: 268435456
717
718
=== Invalid BlockdevRef ===
719
720
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
721
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}}
722
{"return": {}}
723
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
724
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
725
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
726
727
=== Zero size ===
728
729
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
730
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}}
731
{"return": {}}
732
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
733
{"return": {}}
734
@@ -XXX,XX +XXX,XX @@ cluster_size: 8388608
735
736
=== Maximum size ===
737
738
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
739
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}}
740
{"return": {}}
741
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
742
{"return": {}}
743
@@ -XXX,XX +XXX,XX @@ cluster_size: 67108864
744
745
=== Invalid sizes ===
746
747
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
748
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}}
749
{"return": {}}
750
Job failed: Image size too large; max of 64TB
751
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
752
{"return": {}}
753
754
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
755
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}}
756
{"return": {}}
757
Job failed: Image size too large; max of 64TB
758
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
759
{"return": {}}
760
761
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
762
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}}
763
{"return": {}}
764
Job failed: Image size too large; max of 64TB
765
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
766
{"return": {}}
767
768
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
769
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}}
770
{"return": {}}
771
Job failed: Image size too large; max of 64TB
772
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
773
@@ -XXX,XX +XXX,XX @@ Job failed: Image size too large; max of 64TB
774
775
=== Invalid block size ===
776
777
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
778
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}}
779
{"return": {}}
780
Job failed: Block size must be a multiple of 1 MB
781
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
782
{"return": {}}
783
784
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
785
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}}
786
{"return": {}}
787
Job failed: Block size must be a multiple of 1 MB
788
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
789
{"return": {}}
790
791
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
792
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}}
793
{"return": {}}
794
Job failed: Block size must be a power of two
795
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
796
{"return": {}}
797
798
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
799
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}}
800
{"return": {}}
801
Job failed: Block size must not exceed 268435456
802
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
803
{"return": {}}
804
805
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
806
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}}
807
{"return": {}}
808
Job failed: Block size must be a multiple of 1 MB
809
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
810
@@ -XXX,XX +XXX,XX @@ Job failed: Block size must be a multiple of 1 MB
811
812
=== Invalid log size ===
813
814
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
815
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}}
816
{"return": {}}
817
Job failed: Log size must be a multiple of 1 MB
818
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
819
{"return": {}}
820
821
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
822
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}}
823
{"return": {}}
824
Job failed: Log size must be a multiple of 1 MB
825
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
826
{"return": {}}
827
828
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
829
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}}
830
{"return": {}}
831
Job failed: Log size must be smaller than 4 GB
832
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
833
{"return": {}}
834
835
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
836
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}}
837
{"return": {}}
838
Job failed: Log size must be a multiple of 1 MB
839
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
840
diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out
841
index XXXXXXX..XXXXXXX 100644
842
--- a/tests/qemu-iotests/237.out
843
+++ b/tests/qemu-iotests/237.out
844
@@ -XXX,XX +XXX,XX @@
845
=== Successful image creation (defaults) ===
846
847
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
848
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
849
{"return": {}}
850
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
851
{"return": {}}
852
853
-{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node_name": "imgfile"}}
854
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "node-name": "imgfile"}}
855
{"return": {}}
856
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
857
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}}
858
{"return": {}}
859
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
860
{"return": {}}
861
@@ -XXX,XX +XXX,XX @@ Format specific information:
862
863
=== Successful image creation (inline blockdev-add, explicit defaults) ===
864
865
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
866
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
867
{"return": {}}
868
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
869
{"return": {}}
870
871
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
872
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 67108864, "subformat": "monolithicSparse", "zeroed-grain": false}}}
873
{"return": {}}
874
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
875
{"return": {}}
876
@@ -XXX,XX +XXX,XX @@ Format specific information:
877
878
=== Successful image creation (with non-default options) ===
879
880
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
881
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}}
882
{"return": {}}
883
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
884
{"return": {}}
885
886
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
887
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subformat": "monolithicSparse", "zeroed-grain": true}}}
888
{"return": {}}
889
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
890
{"return": {}}
891
@@ -XXX,XX +XXX,XX @@ Format specific information:
892
893
=== Invalid BlockdevRef ===
894
895
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
896
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}}
897
{"return": {}}
898
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
899
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
900
@@ -XXX,XX +XXX,XX @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
901
902
== Valid adapter types ==
903
904
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
905
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432}}}
906
{"return": {}}
907
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
908
{"return": {}}
909
910
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
911
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
912
{"return": {}}
913
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
914
{"return": {}}
915
916
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
917
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 33554432}}}
918
{"return": {}}
919
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
920
{"return": {}}
921
922
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
923
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33554432}}}
924
{"return": {}}
925
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
926
{"return": {}}
927
928
== Invalid adapter types ==
929
930
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
931
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432}}}
932
{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}}
933
934
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
935
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432}}}
936
{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}}
937
938
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
939
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33554432}}}
940
{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'"}}
941
942
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
943
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}}
944
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'options.adapter-type', expected: string"}}
945
946
=== Other subformats ===
947
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/PID-t.vmdk.3', fmt=vmdk size=0 compat6=off hwversion=undefi
948
949
== Missing extent ==
950
951
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
952
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
953
{"return": {}}
954
Job failed: Extent [0] not specified
955
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
956
@@ -XXX,XX +XXX,XX @@ Job failed: Extent [0] not specified
957
958
== Correct extent ==
959
960
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
961
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, "subformat": "monolithicFlat"}}}
962
{"return": {}}
963
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
964
{"return": {}}
965
966
== Extra extent ==
967
968
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
969
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 512, "subformat": "monolithicFlat"}}}
970
{"return": {}}
971
Job failed: List of extents contains unused extents
972
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
973
@@ -XXX,XX +XXX,XX @@ Job failed: List of extents contains unused extents
974
975
= twoGbMaxExtentFlat 512 =
976
977
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
978
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentFlat"}}}
979
{"return": {}}
980
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
981
{"return": {}}
982
@@ -XXX,XX +XXX,XX @@ Format specific information:
983
984
= twoGbMaxExtentSparse 512 =
985
986
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
987
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subformat": "twoGbMaxExtentSparse"}}}
988
{"return": {}}
989
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
990
{"return": {}}
991
@@ -XXX,XX +XXX,XX @@ Format specific information:
992
993
= twoGbMaxExtentFlat 1073741824 =
994
995
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
996
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentFlat"}}}
997
{"return": {}}
998
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
999
{"return": {}}
1000
@@ -XXX,XX +XXX,XX @@ Format specific information:
1001
1002
= twoGbMaxExtentSparse 1073741824 =
1003
1004
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
1005
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824, "subformat": "twoGbMaxExtentSparse"}}}
1006
{"return": {}}
1007
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1008
{"return": {}}
1009
@@ -XXX,XX +XXX,XX @@ Format specific information:
1010
1011
= twoGbMaxExtentFlat 2147483648 =
1012
1013
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
1014
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentFlat"}}}
1015
{"return": {}}
1016
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1017
{"return": {}}
1018
@@ -XXX,XX +XXX,XX @@ Format specific information:
1019
1020
= twoGbMaxExtentSparse 2147483648 =
1021
1022
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
1023
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648, "subformat": "twoGbMaxExtentSparse"}}}
1024
{"return": {}}
1025
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1026
{"return": {}}
1027
@@ -XXX,XX +XXX,XX @@ Format specific information:
1028
1029
= twoGbMaxExtentFlat 5368709120 =
1030
1031
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
1032
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentFlat"}}}
1033
{"return": {}}
1034
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1035
{"return": {}}
1036
@@ -XXX,XX +XXX,XX @@ Format specific information:
1037
1038
= twoGbMaxExtentSparse 5368709120 =
1039
1040
-{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
1041
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "size": 5368709120, "subformat": "twoGbMaxExtentSparse"}}}
1042
{"return": {}}
1043
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
1044
{"return": {}}
1045
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
1046
index XXXXXXX..XXXXXXX 100644
1047
--- a/tests/qemu-iotests/iotests.py
1048
+++ b/tests/qemu-iotests/iotests.py
1049
@@ -XXX,XX +XXX,XX @@ def qemu_img(*args):
1050
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
1051
return exitcode
1052
1053
-def ordered_qmp(qmsg):
1054
+def ordered_qmp(qmsg, conv_keys=True):
1055
# Dictionaries are not ordered prior to 3.6, therefore:
1056
if isinstance(qmsg, list):
1057
return [ordered_qmp(atom) for atom in qmsg]
1058
if isinstance(qmsg, dict):
1059
od = OrderedDict()
1060
for k, v in sorted(qmsg.items()):
1061
- od[k] = ordered_qmp(v)
1062
+ if conv_keys:
1063
+ k = k.replace('_', '-')
1064
+ od[k] = ordered_qmp(v, conv_keys=False)
1065
return od
1066
return qmsg
1067
1068
--
1069
2.20.1
1070
1071
diff view generated by jsdifflib
1
From: Peter Maydell <peter.maydell@linaro.org>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
Taking the address of a field in a packed struct is a bad idea, because
3
LUKS encryption reserves clusters for its own payload data. The size of
4
it might not be actually aligned enough for that pointer type (and
4
this area must be included in the qemu-img measure calculation so that
5
thus cause a crash on dereference on some host architectures). Newer
5
we arrive at the correct minimum required image size.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
8
6
9
There are a few places where the in-place swap function is
7
(Ab)use the qcrypto_block_create() API to determine the payload
10
used on something other than a packed struct field; we convert
8
overhead. We discard the payload data that qcrypto thinks will be
11
those anyway, for consistency.
9
written to the image.
12
10
13
This patch was produced with the following spatch script
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
(and hand-editing to fold a few resulting overlength lines):
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
13
Message-id: 20190218104525.23674-2-stefanha@redhat.com
16
@@
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
expression E;
18
@@
19
-be16_to_cpus(&E);
20
+E = be16_to_cpu(E);
21
@@
22
expression E;
23
@@
24
-be32_to_cpus(&E);
25
+E = be32_to_cpu(E);
26
@@
27
expression E;
28
@@
29
-be64_to_cpus(&E);
30
+E = be64_to_cpu(E);
31
@@
32
expression E;
33
@@
34
-cpu_to_be16s(&E);
35
+E = cpu_to_be16(E);
36
@@
37
expression E;
38
@@
39
-cpu_to_be32s(&E);
40
+E = cpu_to_be32(E);
41
@@
42
expression E;
43
@@
44
-cpu_to_be64s(&E);
45
+E = cpu_to_be64(E);
46
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
49
Tested-by: John Snow <jsnow@redhat.com>
50
Reviewed-by: John Snow <jsnow@redhat.com>
51
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
52
---
15
---
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
16
block/qcow2.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
54
1 file changed, 34 insertions(+), 30 deletions(-)
17
1 file changed, 71 insertions(+), 1 deletion(-)
55
18
56
diff --git a/block/qcow2.c b/block/qcow2.c
19
diff --git a/block/qcow2.c b/block/qcow2.c
57
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
58
--- a/block/qcow2.c
21
--- a/block/qcow2.c
59
+++ b/block/qcow2.c
22
+++ b/block/qcow2.c
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
23
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
61
"pread fail from offset %" PRIu64, offset);
24
return ret;
62
return 1;
25
}
63
}
26
64
- be32_to_cpus(&ext.magic);
27
+static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
65
- be32_to_cpus(&ext.len);
28
+ size_t headerlen, void *opaque, Error **errp)
66
+ ext.magic = be32_to_cpu(ext.magic);
29
+{
67
+ ext.len = be32_to_cpu(ext.len);
30
+ size_t *headerlenp = opaque;
68
offset += sizeof(ext);
31
+
69
#ifdef DEBUG_EXT
32
+ /* Stash away the payload size */
70
printf("ext.magic = 0x%x\n", ext.magic);
33
+ *headerlenp = headerlen;
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
34
+ return 0;
72
"Unable to read CRYPTO header extension");
35
+}
73
return ret;
36
+
74
}
37
+static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
75
- be64_to_cpus(&s->crypto_header.offset);
38
+ size_t offset, const uint8_t *buf, size_t buflen,
76
- be64_to_cpus(&s->crypto_header.length);
39
+ void *opaque, Error **errp)
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
40
+{
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
41
+ /* Discard the bytes, we're not actually writing to an image */
79
42
+ return buflen;
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
43
+}
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
44
+
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
45
+/* Determine the number of bytes for the LUKS payload */
83
return -EINVAL;
46
+static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
84
}
47
+ Error **errp)
85
48
+{
86
- be32_to_cpus(&bitmaps_ext.nb_bitmaps);
49
+ QDict *opts_qdict;
87
- be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
50
+ QDict *cryptoopts_qdict;
88
- be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
51
+ QCryptoBlockCreateOptions *cryptoopts;
89
+ bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
52
+ QCryptoBlock *crypto;
90
+ bitmaps_ext.bitmap_directory_size =
53
+
91
+ be64_to_cpu(bitmaps_ext.bitmap_directory_size);
54
+ /* Extract "encrypt." options into a qdict */
92
+ bitmaps_ext.bitmap_directory_offset =
55
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
93
+ be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
56
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
94
57
+ qobject_unref(opts_qdict);
95
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
58
+
96
error_setg(errp,
59
+ /* Build QCryptoBlockCreateOptions object from qdict */
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
60
+ qdict_put_str(cryptoopts_qdict, "format", "luks");
98
error_setg_errno(errp, -ret, "Could not read qcow2 header");
61
+ cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
99
goto fail;
62
+ qobject_unref(cryptoopts_qdict);
100
}
63
+ if (!cryptoopts) {
101
- be32_to_cpus(&header.magic);
64
+ return false;
102
- be32_to_cpus(&header.version);
65
+ }
103
- be64_to_cpus(&header.backing_file_offset);
66
+
104
- be32_to_cpus(&header.backing_file_size);
67
+ /* Fake LUKS creation in order to determine the payload size */
105
- be64_to_cpus(&header.size);
68
+ crypto = qcrypto_block_create(cryptoopts, "encrypt.",
106
- be32_to_cpus(&header.cluster_bits);
69
+ qcow2_measure_crypto_hdr_init_func,
107
- be32_to_cpus(&header.crypt_method);
70
+ qcow2_measure_crypto_hdr_write_func,
108
- be64_to_cpus(&header.l1_table_offset);
71
+ len, errp);
109
- be32_to_cpus(&header.l1_size);
72
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
110
- be64_to_cpus(&header.refcount_table_offset);
73
+ if (!crypto) {
111
- be32_to_cpus(&header.refcount_table_clusters);
74
+ return false;
112
- be64_to_cpus(&header.snapshots_offset);
75
+ }
113
- be32_to_cpus(&header.nb_snapshots);
76
+
114
+ header.magic = be32_to_cpu(header.magic);
77
+ qcrypto_block_free(crypto);
115
+ header.version = be32_to_cpu(header.version);
78
+ return true;
116
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
79
+}
117
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
80
+
118
+ header.size = be64_to_cpu(header.size);
81
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
119
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
82
Error **errp)
120
+ header.crypt_method = be32_to_cpu(header.crypt_method);
83
{
121
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
84
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
122
+ header.l1_size = be32_to_cpu(header.l1_size);
85
uint64_t virtual_size; /* disk size as seen by guest */
123
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
86
uint64_t refcount_bits;
124
+ header.refcount_table_clusters =
87
uint64_t l2_tables;
125
+ be32_to_cpu(header.refcount_table_clusters);
88
+ uint64_t luks_payload_size = 0;
126
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
89
size_t cluster_size;
127
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
90
int version;
128
91
char *optstr;
129
if (header.magic != QCOW_MAGIC) {
92
PreallocMode prealloc;
130
error_setg(errp, "Image is not in qcow2 format");
93
bool has_backing_file;
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
94
+ bool has_luks;
132
header.refcount_order = 4;
95
133
header.header_length = 72;
96
/* Parse image creation options */
134
} else {
97
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
135
- be64_to_cpus(&header.incompatible_features);
98
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
136
- be64_to_cpus(&header.compatible_features);
99
has_backing_file = !!optstr;
137
- be64_to_cpus(&header.autoclear_features);
100
g_free(optstr);
138
- be32_to_cpus(&header.refcount_order);
101
139
- be32_to_cpus(&header.header_length);
102
+ optstr = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
140
+ header.incompatible_features =
103
+ has_luks = optstr && strcmp(optstr, "luks") == 0;
141
+ be64_to_cpu(header.incompatible_features);
104
+ g_free(optstr);
142
+ header.compatible_features = be64_to_cpu(header.compatible_features);
105
+
143
+ header.autoclear_features = be64_to_cpu(header.autoclear_features);
106
+ if (has_luks) {
144
+ header.refcount_order = be32_to_cpu(header.refcount_order);
107
+ size_t headerlen;
145
+ header.header_length = be32_to_cpu(header.header_length);
108
+
146
109
+ if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
147
if (header.header_length < 104) {
110
+ goto err;
148
error_setg(errp, "qcow2 header too short");
111
+ }
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
112
+
150
goto fail;
113
+ luks_payload_size = ROUND_UP(headerlen, cluster_size);
151
}
114
+ }
152
for(i = 0;i < s->l1_size; i++) {
115
+
153
- be64_to_cpus(&s->l1_table[i]);
116
virtual_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
154
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
117
virtual_size = ROUND_UP(virtual_size, cluster_size);
155
}
118
156
}
119
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
157
120
info = g_new(BlockMeasureInfo, 1);
158
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
121
info->fully_allocated =
159
122
qcow2_calc_prealloc_size(virtual_size, cluster_size,
160
/* Full disk encryption header pointer extension */
123
- ctz32(refcount_bits));
161
if (s->crypto_header.offset != 0) {
124
+ ctz32(refcount_bits)) + luks_payload_size;
162
- cpu_to_be64s(&s->crypto_header.offset);
125
163
- cpu_to_be64s(&s->crypto_header.length);
126
/* Remove data clusters that are not required. This overestimates the
164
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
127
* required size because metadata needed for the fully allocated file is
165
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
166
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
167
&s->crypto_header, sizeof(s->crypto_header),
168
buflen);
169
- be64_to_cpus(&s->crypto_header.offset);
170
- be64_to_cpus(&s->crypto_header.length);
171
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
172
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
173
if (ret < 0) {
174
goto fail;
175
}
176
--
128
--
177
2.19.1
129
2.20.1
178
130
179
131
diff view generated by jsdifflib
New patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
2
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
New patch
1
From: yuchenlin <yuchenlin@synology.com>
1
2
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
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
VDI keeps the whole bitmap in memory, and the maximum size (which is
4
tested here) is 2 GB. This may not be available on all machines, and it
5
rarely is available when running a 32 bit build.
6
7
Fix this by making VM.run_job() return the error string if an error
8
occurred, and checking whether that contains "Could not allocate bmap"
9
in 211. If so, the test is skipped.
10
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 20190218180646.30282-1-mreitz@redhat.com
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
tests/qemu-iotests/211 | 4 +++-
18
tests/qemu-iotests/iotests.py | 5 ++++-
19
2 files changed, 7 insertions(+), 2 deletions(-)
20
21
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/211
24
+++ b/tests/qemu-iotests/211
25
@@ -XXX,XX +XXX,XX @@ def blockdev_create(vm, options):
26
27
if 'return' in result:
28
assert result['return'] == {}
29
- vm.run_job('job0')
30
+ error = vm.run_job('job0')
31
+ if error and 'Could not allocate bmap' in error:
32
+ iotests.notrun('Insufficient memory')
33
iotests.log("")
34
35
with iotests.FilePath('t.vdi') as disk_path, \
36
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/iotests.py
39
+++ b/tests/qemu-iotests/iotests.py
40
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
41
log(result, filters, indent=indent)
42
return result
43
44
+ # Returns None on success, and an error string on failure
45
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
46
+ error = None
47
while True:
48
for ev in self.get_qmp_events_filtered(wait=True):
49
if ev['event'] == 'JOB_STATUS_CHANGE':
50
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
51
result = self.qmp('query-jobs')
52
for j in result['return']:
53
if j['id'] == job:
54
+ error = j['error']
55
log('Job failed: %s' % (j['error']))
56
elif status == 'pending' and not auto_finalize:
57
self.qmp_log('job-finalize', id=job)
58
elif status == 'concluded' and not auto_dismiss:
59
self.qmp_log('job-dismiss', id=job)
60
elif status == 'null':
61
- return
62
+ return error
63
else:
64
iotests.log(ev)
65
66
--
67
2.20.1
68
69
diff view generated by jsdifflib