1
The following changes since commit d9bbfea646e86426d549bd612cd9f91e49aa50c2:
1
The following changes since commit b2f7a038bb4c4fc5ce6b8486e8513dfd97665e2a:
2
2
3
Merge remote-tracking branch 'remotes/riscv/tags/riscv-qemu-upstream-v8.2' into staging (2018-03-09 10:58:57 +0000)
3
Merge remote-tracking branch 'remotes/rth/tags/pull-softfloat-20181104' into staging (2018-11-05 10:32:49 +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 a1be5921e35dcf84ce9e3c9a5c3029cea530a60b:
9
for you to fetch changes up to 1240ac558d348f6c7a5752b1a57c1da58e4efe3e:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-09' into queue-block (2018-03-09 16:09:06 +0100)
11
include: Add a comment to explain the origin of sizes' lookup table (2018-11-05 15:29:59 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches:
15
16
- auto-read-only option to fix commit job when used with -blockdev
17
- Fix help text related qemu-iotests failure (by improving the help text
18
and updating the reference output)
19
- quorum: Add missing checks when adding/removing child nodes
20
- Don't take address of fields in packed structs
21
- vvfat: Fix crash when reporting error about too many files in directory
15
22
16
----------------------------------------------------------------
23
----------------------------------------------------------------
17
Alberto Garcia (8):
24
Alberto Garcia (7):
18
qcow2: Generalize validate_table_offset() into qcow2_validate_table()
25
block: replace "discard" literal with BDRV_OPT_DISCARD macro
19
qcow2: Check L1 table offset in qcow2_snapshot_load_tmp()
26
qcow2: Get the request alignment for encrypted images from QCryptoBlock
20
qcow2: Check L1 table parameters in qcow2_expand_zero_clusters()
27
quorum: Remove quorum_err()
21
qcow2: Check snapshot L1 tables in qcow2_check_metadata_overlap()
28
quorum: Return an error if the blkverify mode has invalid settings
22
qcow2: Check snapshot L1 table in qcow2_snapshot_goto()
29
iotest: Test the blkverify mode of the Quorum driver
23
qcow2: Check snapshot L1 table in qcow2_snapshot_delete()
30
quorum: Forbid adding children in blkverify mode
24
qcow2: Make qemu-img check detect corrupted L1 tables in snapshots
31
iotest: Test x-blockdev-change on a Quorum
25
iotests: Tweak 030 in order to trigger a race condition with parallel jobs
32
33
Cleber Rosa (1):
34
iotests: make 083 specific to raw
26
35
27
Daniel P. Berrangé (1):
36
Daniel P. Berrangé (1):
28
block: implement the bdrv_reopen_prepare helper for LUKS driver
37
crypto: initialize sector size even when opening with no IO flag
29
38
30
Eric Blake (1):
39
Kevin Wolf (12):
31
iotests: Mark all tests executable
40
vpc: Don't leak opts in vpc_open()
41
block: Update flags in bdrv_set_read_only()
42
block: Add auto-read-only option
43
rbd: Close image in qemu_rbd_open() error path
44
block: Require auto-read-only for existing fallbacks
45
nbd: Support auto-read-only option
46
file-posix: Support auto-read-only option
47
curl: Support auto-read-only option
48
gluster: Support auto-read-only option
49
iscsi: Support auto-read-only option
50
block: Make auto-read-only=on default for -drive
51
qemu-iotests: Test auto-read-only with -drive and -blockdev
32
52
33
Fam Zheng (2):
53
Leonid Bloch (2):
34
iotests: Test creating overlay when guest running
54
vdi: Use a literal number of bytes for DEFAULT_CLUSTER_SIZE
35
iotests: Skip test for ENOMEM error
55
include: Add a comment to explain the origin of sizes' lookup table
36
56
37
Kevin Wolf (38):
57
Li Qiang (1):
38
block/qapi: Introduce BlockdevCreateOptions
58
block: change some function return type to bool
39
block/qapi: Add qcow2 create options to schema
40
qcow2: Rename qcow2_co_create2() to qcow2_co_create()
41
qcow2: Let qcow2_create() handle protocol layer
42
qcow2: Pass BlockdevCreateOptions to qcow2_co_create()
43
qcow2: Use BlockdevRef in qcow2_co_create()
44
qcow2: Use QCryptoBlockCreateOptions in qcow2_co_create()
45
qcow2: Handle full/falloc preallocation in qcow2_co_create()
46
util: Add qemu_opts_to_qdict_filtered()
47
test-qemu-opts: Test qemu_opts_append()
48
test-qemu-opts: Test qemu_opts_to_qdict_filtered()
49
qdict: Introduce qdict_rename_keys()
50
qcow2: Use visitor for options in qcow2_create()
51
block: Make bdrv_is_whitelisted() public
52
block: x-blockdev-create QMP command
53
file-posix: Support .bdrv_co_create
54
file-win32: Support .bdrv_co_create
55
gluster: Support .bdrv_co_create
56
rbd: Fix use after free in qemu_rbd_set_keypairs() error path
57
rbd: Factor out qemu_rbd_connect()
58
rbd: Remove non-schema options from runtime_opts
59
rbd: Pass BlockdevOptionsRbd to qemu_rbd_connect()
60
rbd: Support .bdrv_co_create
61
rbd: Assign s->snap/image_name in qemu_rbd_open()
62
rbd: Use qemu_rbd_connect() in qemu_rbd_do_create()
63
nfs: Use QAPI options in nfs_client_open()
64
nfs: Support .bdrv_co_create
65
sheepdog: QAPIfy "redundancy" create option
66
sheepdog: Support .bdrv_co_create
67
ssh: Use QAPI BlockdevOptionsSsh object
68
ssh: QAPIfy host-key-check option
69
ssh: Pass BlockdevOptionsSsh to connect_to_ssh()
70
ssh: Support .bdrv_co_create
71
file-posix: Fix no-op bdrv_truncate() with falloc preallocation
72
block: Fail bdrv_truncate() with negative size
73
qemu-iotests: Test qcow2 over file image creation with QMP
74
qemu-iotests: Test ssh image creation over QMP
75
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-03-09' into queue-block
76
59
77
Paolo Bonzini (6):
60
Max Reitz (5):
78
qcow2: introduce qcow2_write_caches and qcow2_flush_caches
61
option: Make option help nicer to read
79
qcow2: fix flushing after dirty bitmap metadata writes
62
chardev: Indent list of chardevs
80
qcow2: make qcow2_do_open a coroutine_fn
63
qdev-monitor: Make device options help nicer
81
qed: make bdrv_qed_do_open a coroutine_fn
64
object: Make option help nicer to read
82
block: convert bdrv_invalidate_cache callback to coroutine_fn
65
fw_cfg: Drop newline in @file description
83
block: convert bdrv_check callback to coroutine_fn
84
66
85
Stefan Hajnoczi (1):
67
Peter Maydell (5):
86
qemu-iotests: fix 203 migration completion race
68
block/qcow2: Don't take address of fields in packed structs
69
block/qcow: Don't take address of fields in packed structs
70
block/qcow2-bitmap: Don't take address of fields in packed structs
71
block/vhdx: Don't take address of fields in packed structs
72
block/vdi: Don't take address of fields in packed structs
87
73
88
qapi/block-core.json | 326 +++++++++++++++++++++++++-
74
Stefan Weil (1):
89
block/qcow2.h | 12 +-
75
qemu-io-cmds: Fix two format strings
90
include/block/block.h | 2 +
91
include/block/block_int.h | 13 +-
92
include/qapi/qmp/qdict.h | 6 +
93
include/qemu/option.h | 2 +
94
block.c | 138 +++++++++++-
95
block/create.c | 76 +++++++
96
block/crypto.c | 7 +
97
block/file-posix.c | 93 +++++---
98
block/file-win32.c | 47 +++-
99
block/gluster.c | 135 +++++++----
100
block/iscsi.c | 6 +-
101
block/nfs.c | 244 +++++++++-----------
102
block/parallels.c | 17 +-
103
block/qcow2-bitmap.c | 4 +-
104
block/qcow2-cluster.c | 24 +-
105
block/qcow2-refcount.c | 52 ++++-
106
block/qcow2-snapshot.c | 24 +-
107
block/qcow2.c | 552 ++++++++++++++++++++++++++++-----------------
108
block/qed-check.c | 1 +
109
block/qed-table.c | 26 +--
110
block/qed.c | 66 ++++--
111
block/rbd.c | 403 +++++++++++++++++----------------
112
block/sheepdog.c | 321 ++++++++++++++++++--------
113
block/ssh.c | 290 +++++++++++++-----------
114
block/vdi.c | 6 +-
115
block/vhdx.c | 7 +-
116
block/vmdk.c | 7 +-
117
qobject/qdict.c | 34 +++
118
tests/check-qdict.c | 129 +++++++++++
119
tests/test-qemu-opts.c | 253 +++++++++++++++++++++
120
util/qemu-option.c | 42 +++-
121
block/Makefile.objs | 2 +-
122
tests/qemu-iotests/030 | 52 ++++-
123
tests/qemu-iotests/030.out | 4 +-
124
tests/qemu-iotests/049.out | 8 +-
125
tests/qemu-iotests/059 | 5 +-
126
tests/qemu-iotests/080 | 22 +-
127
tests/qemu-iotests/080.out | 58 ++++-
128
tests/qemu-iotests/096 | 0
129
tests/qemu-iotests/112.out | 4 +-
130
tests/qemu-iotests/124 | 0
131
tests/qemu-iotests/129 | 0
132
tests/qemu-iotests/132 | 0
133
tests/qemu-iotests/136 | 0
134
tests/qemu-iotests/139 | 0
135
tests/qemu-iotests/148 | 0
136
tests/qemu-iotests/152 | 0
137
tests/qemu-iotests/153 | 8 +-
138
tests/qemu-iotests/153.out | 7 +-
139
tests/qemu-iotests/163 | 0
140
tests/qemu-iotests/203 | 15 +-
141
tests/qemu-iotests/203.out | 5 +
142
tests/qemu-iotests/205 | 0
143
tests/qemu-iotests/206 | 436 +++++++++++++++++++++++++++++++++++
144
tests/qemu-iotests/206.out | 209 +++++++++++++++++
145
tests/qemu-iotests/207 | 261 +++++++++++++++++++++
146
tests/qemu-iotests/207.out | 75 ++++++
147
tests/qemu-iotests/group | 2 +
148
60 files changed, 3574 insertions(+), 964 deletions(-)
149
create mode 100644 block/create.c
150
mode change 100644 => 100755 tests/qemu-iotests/096
151
mode change 100644 => 100755 tests/qemu-iotests/124
152
mode change 100644 => 100755 tests/qemu-iotests/129
153
mode change 100644 => 100755 tests/qemu-iotests/132
154
mode change 100644 => 100755 tests/qemu-iotests/136
155
mode change 100644 => 100755 tests/qemu-iotests/139
156
mode change 100644 => 100755 tests/qemu-iotests/148
157
mode change 100644 => 100755 tests/qemu-iotests/152
158
mode change 100644 => 100755 tests/qemu-iotests/163
159
mode change 100644 => 100755 tests/qemu-iotests/205
160
create mode 100755 tests/qemu-iotests/206
161
create mode 100644 tests/qemu-iotests/206.out
162
create mode 100755 tests/qemu-iotests/207
163
create mode 100644 tests/qemu-iotests/207.out
164
76
77
Thomas Huth (1):
78
block/vvfat: Fix crash when reporting error about too many files in directory
79
80
qapi/block-core.json | 7 +
81
block/vhdx.h | 12 +-
82
include/block/block.h | 5 +-
83
include/qemu/option.h | 2 +-
84
include/qemu/units.h | 18 +
85
include/sysemu/block-backend.h | 6 +-
86
block.c | 60 ++-
87
block/block-backend.c | 8 +-
88
block/bochs.c | 17 +-
89
block/cloop.c | 16 +-
90
block/curl.c | 8 +-
91
block/dmg.c | 16 +-
92
block/file-posix.c | 19 +-
93
block/gluster.c | 12 +-
94
block/iscsi.c | 8 +-
95
block/nbd-client.c | 10 +-
96
block/qcow.c | 18 +-
97
block/qcow2-bitmap.c | 24 +-
98
block/qcow2.c | 66 +--
99
block/quorum.c | 45 +-
100
block/rbd.c | 14 +-
101
block/vdi.c | 68 +--
102
block/vhdx-endian.c | 118 ++---
103
block/vhdx-log.c | 4 +-
104
block/vhdx.c | 18 +-
105
block/vpc.c | 2 +
106
block/vvfat.c | 15 +-
107
blockdev.c | 3 +-
108
chardev/char.c | 2 +-
109
crypto/block-qcow.c | 2 +
110
qdev-monitor.c | 13 +-
111
qemu-img.c | 4 +-
112
qemu-io-cmds.c | 4 +-
113
util/qemu-option.c | 32 +-
114
vl.c | 15 +-
115
tests/qemu-iotests/081 | 116 +++++
116
tests/qemu-iotests/081.out | 70 +++
117
tests/qemu-iotests/082.out | 956 ++++++++++++++++++++---------------------
118
tests/qemu-iotests/083 | 2 +-
119
tests/qemu-iotests/232 | 147 +++++++
120
tests/qemu-iotests/232.out | 59 +++
121
tests/qemu-iotests/group | 1 +
122
42 files changed, 1266 insertions(+), 776 deletions(-)
123
create mode 100755 tests/qemu-iotests/232
124
create mode 100644 tests/qemu-iotests/232.out
125
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
There is a race between the test's 'query-migrate' QMP command after the
3
When using the vvfat driver with a directory that contains too many files,
4
QMP 'STOP' event and completing the migration:
4
QEMU currently crashes. This can be triggered like this for example:
5
5
6
The test case invokes 'query-migrate' upon receiving 'STOP'. At this
6
mkdir /tmp/vvfattest
7
point the migration thread may still be in the process of completing.
7
cd /tmp/vvfattest
8
Therefore 'query-migrate' can return 'status': 'active' for a brief
8
for ((x=0;x<=513;x++)); do mkdir $x; done
9
window of time instead of 'status': 'completed'. This results in
9
qemu-system-x86_64 -drive \
10
qemu-iotests 203 hanging.
10
file.driver=vvfat,file.dir=.,read-only=on,media=cdrom
11
11
12
Solve the race by enabling the 'events' migration capability, which
12
Seems like read_directory() is changing the mapping->path variable. Make
13
causes QEMU to emit migration-specific QMP events that do not suffer
13
sure we use the right pointer instead.
14
from this race condition. Wait for the QMP 'MIGRATION' event with
15
'status': 'completed'.
16
14
17
Reported-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Thomas Huth <thuth@redhat.com>
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Message-id: 20180305155926.25858-1-stefanha@redhat.com
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
---
17
---
23
tests/qemu-iotests/203 | 15 +++++++++++----
18
block/vvfat.c | 4 ++--
24
tests/qemu-iotests/203.out | 5 +++++
19
1 file changed, 2 insertions(+), 2 deletions(-)
25
2 files changed, 16 insertions(+), 4 deletions(-)
26
20
27
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
21
diff --git a/block/vvfat.c b/block/vvfat.c
28
index XXXXXXX..XXXXXXX 100755
29
--- a/tests/qemu-iotests/203
30
+++ b/tests/qemu-iotests/203
31
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('disk0.img') as disk0_img_path, \
32
node_name='drive1-node', iothread='iothread0',
33
force=True))
34
35
+ iotests.log('Enabling migration QMP events...')
36
+ iotests.log(vm.qmp('migrate-set-capabilities', capabilities=[
37
+ {
38
+ 'capability': 'events',
39
+ 'state': True
40
+ }
41
+ ]))
42
+
43
iotests.log('Starting migration...')
44
iotests.log(vm.qmp('migrate', uri='exec:cat >/dev/null'))
45
while True:
46
- vm.get_qmp_event(wait=60.0)
47
- result = vm.qmp('query-migrate')
48
- status = result.get('return', {}).get('status', None)
49
- if status == 'completed':
50
+ event = vm.event_wait('MIGRATION')
51
+ iotests.log(event, filters=[iotests.filter_qmp_event])
52
+ if event['data']['status'] == 'completed':
53
break
54
diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out
55
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
56
--- a/tests/qemu-iotests/203.out
23
--- a/block/vvfat.c
57
+++ b/tests/qemu-iotests/203.out
24
+++ b/block/vvfat.c
58
@@ -XXX,XX +XXX,XX @@ Launching VM...
25
@@ -XXX,XX +XXX,XX @@ static int init_directories(BDRVVVFATState* s,
59
Setting IOThreads...
26
mapping = array_get(&(s->mapping), i);
60
{u'return': {}}
27
61
{u'return': {}}
28
if (mapping->mode & MODE_DIRECTORY) {
62
+Enabling migration QMP events...
29
+ char *path = mapping->path;
63
+{u'return': {}}
30
mapping->begin = cluster;
64
Starting migration...
31
if(read_directory(s, i)) {
65
{u'return': {}}
32
- error_setg(errp, "Could not read directory %s",
66
+{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'}
33
- mapping->path);
67
+{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'}
34
+ error_setg(errp, "Could not read directory %s", path);
68
+{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'}
35
return -1;
36
}
37
mapping = array_get(&(s->mapping), i);
69
--
38
--
70
2.13.6
39
2.19.1
71
40
72
41
diff view generated by jsdifflib
1
Most callers have their own checks, but something like this should also
1
From: Alberto Garcia <berto@igalia.com>
2
be checked centrally. As it happens, x-blockdev-create can pass negative
3
image sizes to format drivers (because there is no QAPI type that would
4
reject negative numbers) and triggers the check added by this patch.
5
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
---
5
---
10
block.c | 5 +++++
6
block.c | 6 +++---
11
1 file changed, 5 insertions(+)
7
1 file changed, 3 insertions(+), 3 deletions(-)
12
8
13
diff --git a/block.c b/block.c
9
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
11
--- a/block.c
16
+++ b/block.c
12
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, PreallocMode prealloc,
13
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
18
error_setg(errp, "No medium inserted");
14
.help = "try to optimize zero writes (off, on, unmap)",
19
return -ENOMEDIUM;
15
},
16
{
17
- .name = "discard",
18
+ .name = BDRV_OPT_DISCARD,
19
.type = QEMU_OPT_STRING,
20
.help = "discard operation (ignore/off, unmap/on)",
21
},
22
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
23
}
20
}
24
}
21
+ if (offset < 0) {
25
22
+ error_setg(errp, "Image size cannot be negative");
26
- discard = qemu_opt_get(opts, "discard");
23
+ return -EINVAL;
27
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
24
+ }
28
if (discard != NULL) {
25
+
29
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
26
if (!drv->bdrv_truncate) {
30
error_setg(errp, "Invalid discard option");
27
if (bs->file && drv->is_filter) {
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
28
return bdrv_truncate(bs->file, offset, prealloc, errp);
32
33
update_flags_from_options(&reopen_state->flags, opts);
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");
29
--
40
--
30
2.13.6
41
2.19.1
31
42
32
43
diff view generated by jsdifflib
1
All of the simple options are now passed to qcow2_co_create() in a
1
From: Stefan Weil <sw@weilnetz.de>
2
BlockdevCreateOptions object. Still missing: node-name and the
3
encryption options.
4
2
3
Use %zu instead of %zd for unsigned numbers.
4
5
This fixes two error messages from the LSTM static code analyzer:
6
7
This argument should be of type 'ssize_t' but is of type 'unsigned long'
8
9
Signed-off-by: Stefan Weil <sw@weilnetz.de>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
12
---
9
block/qcow2.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++------------
13
qemu-io-cmds.c | 4 ++--
10
1 file changed, 151 insertions(+), 38 deletions(-)
14
1 file changed, 2 insertions(+), 2 deletions(-)
11
15
12
diff --git a/block/qcow2.c b/block/qcow2.c
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
18
--- a/qemu-io-cmds.c
15
+++ b/block/qcow2.c
19
+++ b/qemu-io-cmds.c
16
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
20
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
17
return meta_size + aligned_total_size;
21
memset(cmp_buf, pattern, qiov.size);
18
}
22
if (memcmp(buf, cmp_buf, qiov.size)) {
19
23
printf("Pattern verification failed at offset %"
20
-static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp)
24
- PRId64 ", %zd bytes\n", offset, qiov.size);
21
+static bool validate_cluster_size(size_t cluster_size, Error **errp)
25
+ PRId64 ", %zu bytes\n", offset, qiov.size);
22
{
26
ret = -EINVAL;
23
- size_t cluster_size;
24
- int cluster_bits;
25
-
26
- cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
27
- DEFAULT_CLUSTER_SIZE);
28
- cluster_bits = ctz32(cluster_size);
29
+ int cluster_bits = ctz32(cluster_size);
30
if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
31
(1 << cluster_bits) != cluster_size)
32
{
33
error_setg(errp, "Cluster size must be a power of two between %d and "
34
"%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
35
+ return false;
36
+ }
37
+ return true;
38
+}
39
+
40
+static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp)
41
+{
42
+ size_t cluster_size;
43
+
44
+ cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
45
+ DEFAULT_CLUSTER_SIZE);
46
+ if (!validate_cluster_size(cluster_size, errp)) {
47
return 0;
48
}
49
return cluster_size;
50
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
51
}
52
53
static int coroutine_fn
54
-qcow2_co_create(BlockDriverState *bs, int64_t total_size,
55
- const char *backing_file, const char *backing_format,
56
- int flags, size_t cluster_size, PreallocMode prealloc,
57
- QemuOpts *opts, int version, int refcount_order,
58
- const char *encryptfmt, Error **errp)
59
+qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
60
+ QemuOpts *opts, const char *encryptfmt, Error **errp)
61
{
62
+ BlockdevCreateOptionsQcow2 *qcow2_opts;
63
QDict *options;
64
65
/*
66
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, int64_t total_size,
67
*/
68
BlockBackend *blk;
69
QCowHeader *header;
70
+ size_t cluster_size;
71
+ int version;
72
+ int refcount_order;
73
uint64_t* refcount_table;
74
Error *local_err = NULL;
75
int ret;
76
77
+ /* Validate options and set default values */
78
+ assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2);
79
+ qcow2_opts = &create_options->u.qcow2;
80
+
81
+ if (!QEMU_IS_ALIGNED(qcow2_opts->size, BDRV_SECTOR_SIZE)) {
82
+ error_setg(errp, "Image size must be a multiple of 512 bytes");
83
+ ret = -EINVAL;
84
+ goto out;
85
+ }
86
+
87
+ if (qcow2_opts->has_version) {
88
+ switch (qcow2_opts->version) {
89
+ case BLOCKDEV_QCOW2_VERSION_V2:
90
+ version = 2;
91
+ break;
92
+ case BLOCKDEV_QCOW2_VERSION_V3:
93
+ version = 3;
94
+ break;
95
+ default:
96
+ g_assert_not_reached();
97
+ }
98
+ } else {
99
+ version = 3;
100
+ }
101
+
102
+ if (qcow2_opts->has_cluster_size) {
103
+ cluster_size = qcow2_opts->cluster_size;
104
+ } else {
105
+ cluster_size = DEFAULT_CLUSTER_SIZE;
106
+ }
107
+
108
+ if (!validate_cluster_size(cluster_size, errp)) {
109
+ return -EINVAL;
110
+ }
111
+
112
+ if (!qcow2_opts->has_preallocation) {
113
+ qcow2_opts->preallocation = PREALLOC_MODE_OFF;
114
+ }
115
+ if (qcow2_opts->has_backing_file &&
116
+ qcow2_opts->preallocation != PREALLOC_MODE_OFF)
117
+ {
118
+ error_setg(errp, "Backing file and preallocation cannot be used at "
119
+ "the same time");
120
+ return -EINVAL;
121
+ }
122
+ if (qcow2_opts->has_backing_fmt && !qcow2_opts->has_backing_file) {
123
+ error_setg(errp, "Backing format cannot be used without backing file");
124
+ return -EINVAL;
125
+ }
126
+
127
+ if (!qcow2_opts->has_lazy_refcounts) {
128
+ qcow2_opts->lazy_refcounts = false;
129
+ }
130
+ if (version < 3 && qcow2_opts->lazy_refcounts) {
131
+ error_setg(errp, "Lazy refcounts only supported with compatibility "
132
+ "level 1.1 and above (use compat=1.1 or greater)");
133
+ return -EINVAL;
134
+ }
135
+
136
+ if (!qcow2_opts->has_refcount_bits) {
137
+ qcow2_opts->refcount_bits = 16;
138
+ }
139
+ if (qcow2_opts->refcount_bits > 64 ||
140
+ !is_power_of_2(qcow2_opts->refcount_bits))
141
+ {
142
+ error_setg(errp, "Refcount width must be a power of two and may not "
143
+ "exceed 64 bits");
144
+ return -EINVAL;
145
+ }
146
+ if (version < 3 && qcow2_opts->refcount_bits != 16) {
147
+ error_setg(errp, "Different refcount widths than 16 bits require "
148
+ "compatibility level 1.1 or above (use compat=1.1 or "
149
+ "greater)");
150
+ return -EINVAL;
151
+ }
152
+ refcount_order = ctz32(qcow2_opts->refcount_bits);
153
+
154
+
155
+ /* Create BlockBackend to write to the image */
156
blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
157
ret = blk_insert_bs(blk, bs, errp);
158
if (ret < 0) {
159
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, int64_t total_size,
160
/* We'll update this to correct value later */
161
header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
162
163
- if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) {
164
+ if (qcow2_opts->lazy_refcounts) {
165
header->compatible_features |=
166
cpu_to_be64(QCOW2_COMPAT_LAZY_REFCOUNTS);
167
}
168
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, int64_t total_size,
169
}
170
171
/* Okay, now that we have a valid image, let's give it the right size */
172
- ret = blk_truncate(blk, total_size, PREALLOC_MODE_OFF, errp);
173
+ ret = blk_truncate(blk, qcow2_opts->size, PREALLOC_MODE_OFF, errp);
174
if (ret < 0) {
175
error_prepend(errp, "Could not resize image: ");
176
goto out;
177
}
178
179
/* Want a backing file? There you go.*/
180
- if (backing_file) {
181
- ret = bdrv_change_backing_file(blk_bs(blk), backing_file, backing_format);
182
+ if (qcow2_opts->has_backing_file) {
183
+ const char *backing_format = NULL;
184
+
185
+ if (qcow2_opts->has_backing_fmt) {
186
+ backing_format = BlockdevDriver_str(qcow2_opts->backing_fmt);
187
+ }
188
+
189
+ ret = bdrv_change_backing_file(blk_bs(blk), qcow2_opts->backing_file,
190
+ backing_format);
191
if (ret < 0) {
192
error_setg_errno(errp, -ret, "Could not assign backing file '%s' "
193
- "with format '%s'", backing_file, backing_format);
194
+ "with format '%s'", qcow2_opts->backing_file,
195
+ backing_format);
196
goto out;
197
}
27
}
198
}
28
g_free(cmp_buf);
199
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, int64_t total_size,
29
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
200
}
30
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
201
31
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
202
/* And if we're supposed to preallocate metadata, do that now */
32
printf("Pattern verification failed at offset %"
203
- if (prealloc != PREALLOC_MODE_OFF) {
33
- PRId64 ", %zd bytes\n", ctx->offset, ctx->qiov.size);
204
- ret = preallocate(blk_bs(blk), 0, total_size);
34
+ PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
205
+ if (qcow2_opts->preallocation != PREALLOC_MODE_OFF) {
35
}
206
+ ret = preallocate(blk_bs(blk), 0, qcow2_opts->size);
36
g_free(cmp_buf);
207
if (ret < 0) {
208
error_setg_errno(errp, -ret, "Could not preallocate metadata");
209
goto out;
210
@@ -XXX,XX +XXX,XX @@ out:
211
static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opts,
212
Error **errp)
213
{
214
+ BlockdevCreateOptions create_options;
215
char *backing_file = NULL;
216
char *backing_fmt = NULL;
217
+ BlockdevDriver backing_drv;
218
char *buf = NULL;
219
uint64_t size = 0;
220
int flags = 0;
221
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
222
PreallocMode prealloc;
223
int version;
224
uint64_t refcount_bits;
225
- int refcount_order;
226
char *encryptfmt = NULL;
227
BlockDriverState *bs = NULL;
228
Error *local_err = NULL;
229
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
230
BDRV_SECTOR_SIZE);
231
backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
232
backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
233
+ backing_drv = qapi_enum_parse(&BlockdevDriver_lookup, backing_fmt,
234
+ 0, &local_err);
235
+ if (local_err) {
236
+ error_propagate(errp, local_err);
237
+ ret = -EINVAL;
238
+ goto finish;
239
+ }
240
encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
241
if (encryptfmt) {
242
if (qemu_opt_get(opts, BLOCK_OPT_ENCRYPT)) {
243
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
244
flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
245
}
246
247
- if (backing_file && prealloc != PREALLOC_MODE_OFF) {
248
- error_setg(errp, "Backing file and preallocation cannot be used at "
249
- "the same time");
250
- ret = -EINVAL;
251
- goto finish;
252
- }
253
-
254
- if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) {
255
- error_setg(errp, "Lazy refcounts only supported with compatibility "
256
- "level 1.1 and above (use compat=1.1 or greater)");
257
- ret = -EINVAL;
258
- goto finish;
259
- }
260
-
261
refcount_bits = qcow2_opt_get_refcount_bits_del(opts, version, &local_err);
262
if (local_err) {
263
error_propagate(errp, local_err);
264
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
265
goto finish;
266
}
267
268
- refcount_order = ctz32(refcount_bits);
269
270
/* Create and open the file (protocol layer) */
271
if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
272
+ int refcount_order = ctz32(refcount_bits);
273
int64_t prealloc_size =
274
qcow2_calc_prealloc_size(size, cluster_size, refcount_order);
275
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
276
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
277
}
278
279
/* Create the qcow2 image (format layer) */
280
- ret = qcow2_co_create(bs, size, backing_file, backing_fmt, flags,
281
- cluster_size, prealloc, opts, version, refcount_order,
282
- encryptfmt, errp);
283
+ create_options = (BlockdevCreateOptions) {
284
+ .driver = BLOCKDEV_DRIVER_QCOW2,
285
+ .u.qcow2 = {
286
+ .file = &(BlockdevRef) {
287
+ .type = QTYPE_QSTRING,
288
+ .u.reference = bs->node_name,
289
+ },
290
+ .size = size,
291
+ .has_version = true,
292
+ .version = version == 2
293
+ ? BLOCKDEV_QCOW2_VERSION_V2
294
+ : BLOCKDEV_QCOW2_VERSION_V3,
295
+ .has_backing_file = (backing_file != NULL),
296
+ .backing_file = backing_file,
297
+ .has_backing_fmt = (backing_fmt != NULL),
298
+ .backing_fmt = backing_drv,
299
+ .has_cluster_size = true,
300
+ .cluster_size = cluster_size,
301
+ .has_preallocation = true,
302
+ .preallocation = prealloc,
303
+ .has_lazy_refcounts = true,
304
+ .lazy_refcounts = (flags & BLOCK_FLAG_LAZY_REFCOUNTS),
305
+ .has_refcount_bits = true,
306
+ .refcount_bits = refcount_bits,
307
+ },
308
+ };
309
+ ret = qcow2_co_create(bs, &create_options, opts, encryptfmt, errp);
310
if (ret < 0) {
311
goto finish;
312
}
37
}
313
--
38
--
314
2.13.6
39
2.19.1
315
40
316
41
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
It is called from qcow2_invalidate_cache in coroutine context (incoming
3
Taking the address of a field in a packed struct is a bad idea, because
4
migration runs in a coroutine), so it's cleaner if metadata is always
4
it might not be actually aligned enough for that pointer type (and
5
loaded from a coroutine.
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.
6
8
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
There are a few places where the in-place swap function is
8
Message-Id: <1516279431-30424-4-git-send-email-pbonzini@redhat.com>
10
used on something other than a packed struct field; we convert
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
those anyway, for consistency.
12
13
This patch was produced with the following spatch script
14
(and hand-editing to fold a few resulting overlength lines):
15
16
@@
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
51
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
52
---
12
block/qcow2.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
53
block/qcow2.c | 64 +++++++++++++++++++++++++++------------------------
13
1 file changed, 41 insertions(+), 5 deletions(-)
54
1 file changed, 34 insertions(+), 30 deletions(-)
14
55
15
diff --git a/block/qcow2.c b/block/qcow2.c
56
diff --git a/block/qcow2.c b/block/qcow2.c
16
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.c
58
--- a/block/qcow2.c
18
+++ b/block/qcow2.c
59
+++ b/block/qcow2.c
19
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
60
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
20
return ret;
61
"pread fail from offset %" PRIu64, offset);
21
}
62
return 1;
22
63
}
23
-static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
64
- be32_to_cpus(&ext.magic);
24
- Error **errp)
65
- be32_to_cpus(&ext.len);
25
+/* Called with s->lock held. */
66
+ ext.magic = be32_to_cpu(ext.magic);
26
+static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
67
+ ext.len = be32_to_cpu(ext.len);
27
+ int flags, Error **errp)
68
offset += sizeof(ext);
28
{
69
#ifdef DEBUG_EXT
29
BDRVQcow2State *s = bs->opaque;
70
printf("ext.magic = 0x%x\n", ext.magic);
30
unsigned int len, i;
71
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
31
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
72
"Unable to read CRYPTO header extension");
73
return ret;
74
}
75
- be64_to_cpus(&s->crypto_header.offset);
76
- be64_to_cpus(&s->crypto_header.length);
77
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
78
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
79
80
if ((s->crypto_header.offset % s->cluster_size) != 0) {
81
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
82
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
83
return -EINVAL;
84
}
85
86
- be32_to_cpus(&bitmaps_ext.nb_bitmaps);
87
- be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
88
- be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
89
+ bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
90
+ bitmaps_ext.bitmap_directory_size =
91
+ be64_to_cpu(bitmaps_ext.bitmap_directory_size);
92
+ bitmaps_ext.bitmap_directory_offset =
93
+ be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
94
95
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
96
error_setg(errp,
97
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
98
error_setg_errno(errp, -ret, "Could not read qcow2 header");
99
goto fail;
100
}
101
- be32_to_cpus(&header.magic);
102
- be32_to_cpus(&header.version);
103
- be64_to_cpus(&header.backing_file_offset);
104
- be32_to_cpus(&header.backing_file_size);
105
- be64_to_cpus(&header.size);
106
- be32_to_cpus(&header.cluster_bits);
107
- be32_to_cpus(&header.crypt_method);
108
- be64_to_cpus(&header.l1_table_offset);
109
- be32_to_cpus(&header.l1_size);
110
- be64_to_cpus(&header.refcount_table_offset);
111
- be32_to_cpus(&header.refcount_table_clusters);
112
- be64_to_cpus(&header.snapshots_offset);
113
- be32_to_cpus(&header.nb_snapshots);
114
+ header.magic = be32_to_cpu(header.magic);
115
+ header.version = be32_to_cpu(header.version);
116
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
117
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
118
+ header.size = be64_to_cpu(header.size);
119
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
120
+ header.crypt_method = be32_to_cpu(header.crypt_method);
121
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
122
+ header.l1_size = be32_to_cpu(header.l1_size);
123
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
124
+ header.refcount_table_clusters =
125
+ be32_to_cpu(header.refcount_table_clusters);
126
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
127
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
128
129
if (header.magic != QCOW_MAGIC) {
130
error_setg(errp, "Image is not in qcow2 format");
131
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
132
header.refcount_order = 4;
133
header.header_length = 72;
134
} else {
135
- be64_to_cpus(&header.incompatible_features);
136
- be64_to_cpus(&header.compatible_features);
137
- be64_to_cpus(&header.autoclear_features);
138
- be32_to_cpus(&header.refcount_order);
139
- be32_to_cpus(&header.header_length);
140
+ header.incompatible_features =
141
+ be64_to_cpu(header.incompatible_features);
142
+ header.compatible_features = be64_to_cpu(header.compatible_features);
143
+ header.autoclear_features = be64_to_cpu(header.autoclear_features);
144
+ header.refcount_order = be32_to_cpu(header.refcount_order);
145
+ header.header_length = be32_to_cpu(header.header_length);
146
147
if (header.header_length < 104) {
148
error_setg(errp, "qcow2 header too short");
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
150
goto fail;
151
}
152
for(i = 0;i < s->l1_size; i++) {
153
- be64_to_cpus(&s->l1_table[i]);
154
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
32
}
155
}
33
}
156
}
34
157
35
- /* Initialise locks */
158
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
36
- qemu_co_mutex_init(&s->lock);
159
37
bs->supported_zero_flags = header.version >= 3 ? BDRV_REQ_MAY_UNMAP : 0;
160
/* Full disk encryption header pointer extension */
38
161
if (s->crypto_header.offset != 0) {
39
/* Repair image if dirty */
162
- cpu_to_be64s(&s->crypto_header.offset);
40
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
163
- cpu_to_be64s(&s->crypto_header.length);
41
return ret;
164
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
42
}
165
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
43
166
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
44
+typedef struct QCow2OpenCo {
167
&s->crypto_header, sizeof(s->crypto_header),
45
+ BlockDriverState *bs;
168
buflen);
46
+ QDict *options;
169
- be64_to_cpus(&s->crypto_header.offset);
47
+ int flags;
170
- be64_to_cpus(&s->crypto_header.length);
48
+ Error **errp;
171
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
49
+ int ret;
172
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
50
+} QCow2OpenCo;
173
if (ret < 0) {
51
+
174
goto fail;
52
+static void coroutine_fn qcow2_open_entry(void *opaque)
175
}
53
+{
54
+ QCow2OpenCo *qoc = opaque;
55
+ BDRVQcow2State *s = qoc->bs->opaque;
56
+
57
+ qemu_co_mutex_lock(&s->lock);
58
+ qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
59
+ qemu_co_mutex_unlock(&s->lock);
60
+}
61
+
62
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
63
Error **errp)
64
{
65
+ BDRVQcow2State *s = bs->opaque;
66
+ QCow2OpenCo qoc = {
67
+ .bs = bs,
68
+ .options = options,
69
+ .flags = flags,
70
+ .errp = errp,
71
+ .ret = -EINPROGRESS
72
+ };
73
+
74
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
75
false, errp);
76
if (!bs->file) {
77
return -EINVAL;
78
}
79
80
- return qcow2_do_open(bs, options, flags, errp);
81
+ /* Initialise locks */
82
+ qemu_co_mutex_init(&s->lock);
83
+
84
+ if (qemu_in_coroutine()) {
85
+ /* From bdrv_co_create. */
86
+ qcow2_open_entry(&qoc);
87
+ } else {
88
+ qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
89
+ BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
90
+ }
91
+ return qoc.ret;
92
}
93
94
static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
95
--
176
--
96
2.13.6
177
2.19.1
97
178
98
179
diff view generated by jsdifflib
1
Using the QAPI visitor to turn all options into QAPI BlockdevOptionsNfs
1
From: Peter Maydell <peter.maydell@linaro.org>
2
simplifies the code a lot. It will also be useful for implementing the
3
QAPI based .bdrv_co_create callback.
4
2
3
Taking the address of a field in a packed struct is a bad idea, because
4
it might not be actually aligned enough for that pointer type (and
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
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
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>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
51
---
8
block/nfs.c | 176 ++++++++++++++++++------------------------------------------
52
block/qcow.c | 18 +++++++++---------
9
1 file changed, 53 insertions(+), 123 deletions(-)
53
1 file changed, 9 insertions(+), 9 deletions(-)
10
54
11
diff --git a/block/nfs.c b/block/nfs.c
55
diff --git a/block/qcow.c b/block/qcow.c
12
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
13
--- a/block/nfs.c
57
--- a/block/qcow.c
14
+++ b/block/nfs.c
58
+++ b/block/qcow.c
15
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nfs_co_flush(BlockDriverState *bs)
59
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
16
return task.ret;
60
if (ret < 0) {
17
}
18
19
-static QemuOptsList runtime_opts = {
20
- .name = "nfs",
21
- .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
22
- .desc = {
23
- {
24
- .name = "path",
25
- .type = QEMU_OPT_STRING,
26
- .help = "Path of the image on the host",
27
- },
28
- {
29
- .name = "user",
30
- .type = QEMU_OPT_NUMBER,
31
- .help = "UID value to use when talking to the server",
32
- },
33
- {
34
- .name = "group",
35
- .type = QEMU_OPT_NUMBER,
36
- .help = "GID value to use when talking to the server",
37
- },
38
- {
39
- .name = "tcp-syn-count",
40
- .type = QEMU_OPT_NUMBER,
41
- .help = "Number of SYNs to send during the session establish",
42
- },
43
- {
44
- .name = "readahead-size",
45
- .type = QEMU_OPT_NUMBER,
46
- .help = "Set the readahead size in bytes",
47
- },
48
- {
49
- .name = "page-cache-size",
50
- .type = QEMU_OPT_NUMBER,
51
- .help = "Set the pagecache size in bytes",
52
- },
53
- {
54
- .name = "debug",
55
- .type = QEMU_OPT_NUMBER,
56
- .help = "Set the NFS debug level (max 2)",
57
- },
58
- { /* end of list */ }
59
- },
60
-};
61
-
62
static void nfs_detach_aio_context(BlockDriverState *bs)
63
{
64
NFSClient *client = bs->opaque;
65
@@ -XXX,XX +XXX,XX @@ static void nfs_file_close(BlockDriverState *bs)
66
nfs_client_close(client);
67
}
68
69
-static NFSServer *nfs_config(QDict *options, Error **errp)
70
-{
71
- NFSServer *server = NULL;
72
- QDict *addr = NULL;
73
- QObject *crumpled_addr = NULL;
74
- Visitor *iv = NULL;
75
- Error *local_error = NULL;
76
-
77
- qdict_extract_subqdict(options, &addr, "server.");
78
- if (!qdict_size(addr)) {
79
- error_setg(errp, "NFS server address missing");
80
- goto out;
81
- }
82
-
83
- crumpled_addr = qdict_crumple(addr, errp);
84
- if (!crumpled_addr) {
85
- goto out;
86
- }
87
-
88
- /*
89
- * Caution: this works only because all scalar members of
90
- * NFSServer are QString in @crumpled_addr. The visitor expects
91
- * @crumpled_addr to be typed according to the QAPI schema. It
92
- * is when @options come from -blockdev or blockdev_add. But when
93
- * they come from -drive, they're all QString.
94
- */
95
- iv = qobject_input_visitor_new(crumpled_addr);
96
- visit_type_NFSServer(iv, NULL, &server, &local_error);
97
- if (local_error) {
98
- error_propagate(errp, local_error);
99
- goto out;
100
- }
101
-
102
-out:
103
- QDECREF(addr);
104
- qobject_decref(crumpled_addr);
105
- visit_free(iv);
106
- return server;
107
-}
108
-
109
-
110
-static int64_t nfs_client_open(NFSClient *client, QDict *options,
111
+static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
112
int flags, int open_flags, Error **errp)
113
{
114
int64_t ret = -EINVAL;
115
- QemuOpts *opts = NULL;
116
- Error *local_err = NULL;
117
struct stat st;
118
char *file = NULL, *strp = NULL;
119
120
qemu_mutex_init(&client->mutex);
121
- opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
122
- qemu_opts_absorb_qdict(opts, options, &local_err);
123
- if (local_err) {
124
- error_propagate(errp, local_err);
125
- ret = -EINVAL;
126
- goto fail;
127
- }
128
129
- client->path = g_strdup(qemu_opt_get(opts, "path"));
130
- if (!client->path) {
131
- ret = -EINVAL;
132
- error_setg(errp, "No path was specified");
133
- goto fail;
134
- }
135
+ client->path = g_strdup(opts->path);
136
137
strp = strrchr(client->path, '/');
138
if (strp == NULL) {
139
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
140
file = g_strdup(strp);
141
*strp = 0;
142
143
- /* Pop the config into our state object, Exit if invalid */
144
- client->server = nfs_config(options, errp);
145
- if (!client->server) {
146
- ret = -EINVAL;
147
- goto fail;
148
- }
149
+ /* Steal the NFSServer object from opts; set the original pointer to NULL
150
+ * to avoid use after free and double free. */
151
+ client->server = opts->server;
152
+ opts->server = NULL;
153
154
client->context = nfs_init_context();
155
if (client->context == NULL) {
156
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
157
goto fail;
61
goto fail;
158
}
62
}
159
63
- be32_to_cpus(&header.magic);
160
- if (qemu_opt_get(opts, "user")) {
64
- be32_to_cpus(&header.version);
161
- client->uid = qemu_opt_get_number(opts, "user", 0);
65
- be64_to_cpus(&header.backing_file_offset);
162
+ if (opts->has_user) {
66
- be32_to_cpus(&header.backing_file_size);
163
+ client->uid = opts->user;
67
- be32_to_cpus(&header.mtime);
164
nfs_set_uid(client->context, client->uid);
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,
165
}
83
}
166
84
167
- if (qemu_opt_get(opts, "group")) {
85
for(i = 0;i < s->l1_size; i++) {
168
- client->gid = qemu_opt_get_number(opts, "group", 0);
86
- be64_to_cpus(&s->l1_table[i]);
169
+ if (opts->has_group) {
87
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
170
+ client->gid = opts->group;
171
nfs_set_gid(client->context, client->gid);
172
}
88
}
173
89
174
- if (qemu_opt_get(opts, "tcp-syn-count")) {
90
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
175
- client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0);
176
+ if (opts->has_tcp_syn_count) {
177
+ client->tcp_syncnt = opts->tcp_syn_count;
178
nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
179
}
180
181
#ifdef LIBNFS_FEATURE_READAHEAD
182
- if (qemu_opt_get(opts, "readahead-size")) {
183
+ if (opts->has_readahead_size) {
184
if (open_flags & BDRV_O_NOCACHE) {
185
error_setg(errp, "Cannot enable NFS readahead "
186
"if cache.direct = on");
187
goto fail;
188
}
189
- client->readahead = qemu_opt_get_number(opts, "readahead-size", 0);
190
+ client->readahead = opts->readahead_size;
191
if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
192
warn_report("Truncating NFS readahead size to %d",
193
QEMU_NFS_MAX_READAHEAD_SIZE);
194
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
195
#endif
196
197
#ifdef LIBNFS_FEATURE_PAGECACHE
198
- if (qemu_opt_get(opts, "page-cache-size")) {
199
+ if (opts->has_page_cache_size) {
200
if (open_flags & BDRV_O_NOCACHE) {
201
error_setg(errp, "Cannot enable NFS pagecache "
202
"if cache.direct = on");
203
goto fail;
204
}
205
- client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0);
206
+ client->pagecache = opts->page_cache_size;
207
if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
208
warn_report("Truncating NFS pagecache size to %d pages",
209
QEMU_NFS_MAX_PAGECACHE_SIZE);
210
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
211
#endif
212
213
#ifdef LIBNFS_FEATURE_DEBUG
214
- if (qemu_opt_get(opts, "debug")) {
215
- client->debug = qemu_opt_get_number(opts, "debug", 0);
216
+ if (opts->has_debug) {
217
+ client->debug = opts->debug;
218
/* limit the maximum debug level to avoid potential flooding
219
* of our log files. */
220
if (client->debug > QEMU_NFS_MAX_DEBUG_LEVEL) {
221
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
222
fail:
223
nfs_client_close(client);
224
out:
225
- qemu_opts_del(opts);
226
g_free(file);
227
return ret;
228
}
229
230
+static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
231
+ int flags, int open_flags, Error **errp)
232
+{
233
+ BlockdevOptionsNfs *opts = NULL;
234
+ QObject *crumpled = NULL;
235
+ Visitor *v;
236
+ Error *local_err = NULL;
237
+ int ret;
238
+
239
+ crumpled = qdict_crumple(options, errp);
240
+ if (crumpled == NULL) {
241
+ return -EINVAL;
242
+ }
243
+
244
+ v = qobject_input_visitor_new_keyval(crumpled);
245
+ visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err);
246
+ visit_free(v);
247
+
248
+ if (local_err) {
249
+ error_propagate(errp, local_err);
250
+ ret = -EINVAL;
251
+ goto fail;
252
+ }
253
+
254
+ ret = nfs_client_open(client, opts, flags, open_flags, errp);
255
+fail:
256
+ qobject_decref(crumpled);
257
+ qapi_free_BlockdevOptionsNfs(opts);
258
+ return ret;
259
+}
260
+
261
static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
262
Error **errp) {
263
NFSClient *client = bs->opaque;
264
@@ -XXX,XX +XXX,XX @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
265
266
client->aio_context = bdrv_get_aio_context(bs);
267
268
- ret = nfs_client_open(client, options,
269
- (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY,
270
- bs->open_flags, errp);
271
+ ret = nfs_client_open_qdict(client, options,
272
+ (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY,
273
+ bs->open_flags, errp);
274
if (ret < 0) {
275
return ret;
276
}
277
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
278
goto out;
279
}
280
281
- ret = nfs_client_open(client, options, O_CREAT, 0, errp);
282
+ ret = nfs_client_open_qdict(client, options, O_CREAT, 0, errp);
283
if (ret < 0) {
284
goto out;
285
}
286
--
91
--
287
2.13.6
92
2.19.1
288
93
289
94
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
update_header_sync itself does not need to flush the caches to disk.
3
Taking the address of a field in a packed struct is a bad idea, because
4
The only paths that allocate clusters are:
4
it might not be actually aligned enough for that pointer type (and
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.
5
8
6
- bitmap_list_store with in_place=false, called by update_ext_header_and_dir
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
7
12
8
- store_bitmap_data, called by store_bitmap
13
This patch was produced with the following spatch script:
9
14
10
- store_bitmap, called by qcow2_store_persistent_dirty_bitmaps and
15
@@
11
followed by update_ext_header_and_dir
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);
12
45
13
So in the end the central place where we need to flush the caches
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
is update_ext_header_and_dir.
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
48
Tested-by: John Snow <jsnow@redhat.com>
16
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
49
Reviewed-by: John Snow <jsnow@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
50
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
51
---
19
block/qcow2-bitmap.c | 4 ++--
52
block/qcow2-bitmap.c | 24 ++++++++++++------------
20
1 file changed, 2 insertions(+), 2 deletions(-)
53
1 file changed, 12 insertions(+), 12 deletions(-)
21
54
22
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
55
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
23
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-bitmap.c
57
--- a/block/qcow2-bitmap.c
25
+++ b/block/qcow2-bitmap.c
58
+++ b/block/qcow2-bitmap.c
26
@@ -XXX,XX +XXX,XX @@ static int update_header_sync(BlockDriverState *bs)
59
@@ -XXX,XX +XXX,XX @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
27
return ret;
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]);
28
}
65
}
29
30
- return bdrv_flush(bs);
31
+ return bdrv_flush(bs->file->bs);
32
}
66
}
33
67
34
static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
68
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
35
@@ -XXX,XX +XXX,XX @@ static int update_ext_header_and_dir(BlockDriverState *bs,
69
}
36
return ret;
70
37
}
71
for (i = 0; i < tb->size; ++i) {
38
72
- be64_to_cpus(&table[i]);
39
- ret = bdrv_flush(bs->file->bs);
73
+ table[i] = be64_to_cpu(table[i]);
40
+ ret = qcow2_flush_caches(bs);
74
ret = check_table_entry(table[i], s->cluster_size);
41
if (ret < 0) {
75
if (ret < 0) {
42
goto fail;
76
goto fail;
43
}
77
@@ -XXX,XX +XXX,XX @@ fail:
78
79
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
80
{
81
- be64_to_cpus(&entry->bitmap_table_offset);
82
- be32_to_cpus(&entry->bitmap_table_size);
83
- be32_to_cpus(&entry->flags);
84
- be16_to_cpus(&entry->name_size);
85
- be32_to_cpus(&entry->extra_data_size);
86
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
87
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
88
+ entry->flags = be32_to_cpu(entry->flags);
89
+ entry->name_size = be16_to_cpu(entry->name_size);
90
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
91
}
92
93
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
94
{
95
- cpu_to_be64s(&entry->bitmap_table_offset);
96
- cpu_to_be32s(&entry->bitmap_table_size);
97
- cpu_to_be32s(&entry->flags);
98
- cpu_to_be16s(&entry->name_size);
99
- cpu_to_be32s(&entry->extra_data_size);
100
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
101
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
102
+ entry->flags = cpu_to_be32(entry->flags);
103
+ entry->name_size = cpu_to_be16(entry->name_size);
104
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
105
}
106
107
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
44
--
108
--
45
2.13.6
109
2.19.1
46
110
47
111
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
2
3
This patch tweaks TestParallelOps in iotest 030 so it allocates data
3
The qcow2 block driver expects to see a valid sector size even when it
4
in smaller regions (256KB/512KB instead of 512KB/1MB) and the
4
has opened the crypto layer with QCRYPTO_BLOCK_OPEN_NO_IO.
5
block-stream job in test_stream_commit() only needs to copy data that
6
is at the very end of the image.
7
5
8
This way when the block-stream job is awakened it will finish right
6
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
9
away without any chance of being stopped by block_job_sleep_ns(). This
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
triggers the bug that was fixed by 3d5d319e1221082974711af1d09d82f and
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
1a63a907507fbbcfaee3f622907ec24 and is therefore a more useful test
9
---
12
case for parallel block jobs.
10
crypto/block-qcow.c | 2 ++
11
1 file changed, 2 insertions(+)
13
12
14
After this patch the aforementiond bug can also be reproduced with the
13
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
15
test_stream_parallel() test case.
16
17
Since with this change the stream job in test_stream_commit() finishes
18
early, this patch introduces a similar test case where both jobs are
19
slowed down so they can actually run in parallel.
20
21
Signed-off-by: Alberto Garcia <berto@igalia.com>
22
Cc: John Snow <jsnow@redhat.com>
23
Message-id: 20180306130121.30243-1-berto@igalia.com
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
tests/qemu-iotests/030 | 52 ++++++++++++++++++++++++++++++++++++++--------
27
tests/qemu-iotests/030.out | 4 ++--
28
2 files changed, 45 insertions(+), 11 deletions(-)
29
30
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
31
index XXXXXXX..XXXXXXX 100755
32
--- a/tests/qemu-iotests/030
33
+++ b/tests/qemu-iotests/030
34
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(iotests.QMPTestCase):
35
class TestParallelOps(iotests.QMPTestCase):
36
num_ops = 4 # Number of parallel block-stream operations
37
num_imgs = num_ops * 2 + 1
38
- image_len = num_ops * 1024 * 1024
39
+ image_len = num_ops * 512 * 1024
40
imgs = []
41
42
def setUp(self):
43
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
44
'-o', 'backing_file=%s' % self.imgs[i-1], self.imgs[i])
45
46
# Put data into the images we are copying data from
47
- for i in range(self.num_imgs / 2):
48
- img_index = i * 2 + 1
49
- # Alternate between 512k and 1M.
50
+ odd_img_indexes = [x for x in reversed(range(self.num_imgs)) if x % 2 == 1]
51
+ for i in range(len(odd_img_indexes)):
52
+ # Alternate between 256KB and 512KB.
53
# This way jobs will not finish in the same order they were created
54
- num_kb = 512 + 512 * (i % 2)
55
+ num_kb = 256 + 256 * (i % 2)
56
qemu_io('-f', iotests.imgfmt,
57
- '-c', 'write -P %d %d %d' % (i, i*1024*1024, num_kb * 1024),
58
- self.imgs[img_index])
59
+ '-c', 'write -P 0xFF %dk %dk' % (i * 512, num_kb),
60
+ self.imgs[odd_img_indexes[i]])
61
62
# Attach the drive to the VM
63
self.vm = iotests.VM()
64
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
65
self.wait_until_completed(drive='commit-drive0')
66
67
# Test a block-stream and a block-commit job in parallel
68
- def test_stream_commit(self):
69
+ # Here the stream job is supposed to finish quickly in order to reproduce
70
+ # the scenario that triggers the bug fixed in 3d5d319e1221 and 1a63a907507
71
+ def test_stream_commit_1(self):
72
self.assertLessEqual(8, self.num_imgs)
73
self.assert_no_active_block_jobs()
74
75
# Stream from node0 into node2
76
- result = self.vm.qmp('block-stream', device='node2', job_id='node2')
77
+ result = self.vm.qmp('block-stream', device='node2', base_node='node0', job_id='node2')
78
self.assert_qmp(result, 'return', {})
79
80
# Commit from the active layer into node3
81
@@ -XXX,XX +XXX,XX @@ class TestParallelOps(iotests.QMPTestCase):
82
83
self.assert_no_active_block_jobs()
84
85
+ # This is similar to test_stream_commit_1 but both jobs are slowed
86
+ # down so they can run in parallel for a little while.
87
+ def test_stream_commit_2(self):
88
+ self.assertLessEqual(8, self.num_imgs)
89
+ self.assert_no_active_block_jobs()
90
+
91
+ # Stream from node0 into node4
92
+ result = self.vm.qmp('block-stream', device='node4', base_node='node0', job_id='node4', speed=1024*1024)
93
+ self.assert_qmp(result, 'return', {})
94
+
95
+ # Commit from the active layer into node5
96
+ result = self.vm.qmp('block-commit', device='drive0', base=self.imgs[5], speed=1024*1024)
97
+ self.assert_qmp(result, 'return', {})
98
+
99
+ # Wait for all jobs to be finished.
100
+ pending_jobs = ['node4', 'drive0']
101
+ while len(pending_jobs) > 0:
102
+ for event in self.vm.get_qmp_events(wait=True):
103
+ if event['event'] == 'BLOCK_JOB_COMPLETED':
104
+ node_name = self.dictpath(event, 'data/device')
105
+ self.assertTrue(node_name in pending_jobs)
106
+ self.assert_qmp_absent(event, 'data/error')
107
+ pending_jobs.remove(node_name)
108
+ if event['event'] == 'BLOCK_JOB_READY':
109
+ self.assert_qmp(event, 'data/device', 'drive0')
110
+ self.assert_qmp(event, 'data/type', 'commit')
111
+ self.assert_qmp_absent(event, 'data/error')
112
+ self.assertTrue('drive0' in pending_jobs)
113
+ self.vm.qmp('block-job-complete', device='drive0')
114
+
115
+ self.assert_no_active_block_jobs()
116
+
117
# Test the base_node parameter
118
def test_stream_base_node_name(self):
119
self.assert_no_active_block_jobs()
120
diff --git a/tests/qemu-iotests/030.out b/tests/qemu-iotests/030.out
121
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
122
--- a/tests/qemu-iotests/030.out
15
--- a/crypto/block-qcow.c
123
+++ b/tests/qemu-iotests/030.out
16
+++ b/crypto/block-qcow.c
124
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ qcrypto_block_qcow_open(QCryptoBlock *block,
125
-.......................
18
Error **errp)
126
+........................
19
{
127
----------------------------------------------------------------------
20
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
128
-Ran 23 tests
21
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
129
+Ran 24 tests
22
+ block->payload_offset = 0;
130
23
return 0;
131
OK
24
} else {
25
if (!options->u.qcow.key_secret) {
132
--
26
--
133
2.13.6
27
2.19.1
134
28
135
29
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This function checks that the offset and size of a table are valid.
3
This doesn't have any practical effect at the moment because the
4
4
values of BDRV_SECTOR_SIZE, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE and
5
While the offset checks are fine, the size check is too generic, since
5
QCRYPTO_BLOCK_QCOW_SECTOR_SIZE are all the same (512 bytes), but
6
it only verifies that the total size in bytes fits in a 64-bit
6
future encryption methods could have different requirements.
7
integer. In practice all tables used in qcow2 have much smaller size
8
limits, so the size needs to be checked again for each table using its
9
actual limit.
10
11
This patch generalizes this function by allowing the caller to specify
12
the maximum size for that table. In addition to that it allows passing
13
an Error variable.
14
15
The function is also renamed and made public since we're going to use
16
it in other parts of the code.
17
7
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
11
---
22
block/qcow2.h | 10 +++---
12
block/qcow2.c | 2 +-
23
block/qcow2.c | 77 ++++++++++++++++++----------------------------
13
1 file changed, 1 insertion(+), 1 deletion(-)
24
tests/qemu-iotests/080.out | 16 +++++-----
25
3 files changed, 43 insertions(+), 60 deletions(-)
26
14
27
diff --git a/block/qcow2.h b/block/qcow2.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/qcow2.h
30
+++ b/block/qcow2.h
31
@@ -XXX,XX +XXX,XX @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
32
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
33
}
34
35
-static inline uint64_t qcow2_max_refcount_clusters(BDRVQcow2State *s)
36
-{
37
- return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits;
38
-}
39
-
40
static inline QCow2ClusterType qcow2_get_cluster_type(uint64_t l2_entry)
41
{
42
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
43
@@ -XXX,XX +XXX,XX @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
44
int64_t size, const char *message_format, ...)
45
GCC_FMT_ATTR(5, 6);
46
47
+int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
48
+ uint64_t entries, size_t entry_len,
49
+ int64_t max_size_bytes, const char *table_name,
50
+ Error **errp);
51
+
52
/* qcow2-refcount.c functions */
53
int qcow2_refcount_init(BlockDriverState *bs);
54
void qcow2_refcount_close(BlockDriverState *bs);
55
diff --git a/block/qcow2.c b/block/qcow2.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
56
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
57
--- a/block/qcow2.c
17
--- a/block/qcow2.c
58
+++ b/block/qcow2.c
18
+++ b/block/qcow2.c
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
19
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
60
return ret;
20
61
}
21
if (bs->encrypted) {
62
22
/* Encryption works on a sector granularity */
63
-static int validate_table_offset(BlockDriverState *bs, uint64_t offset,
23
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
64
- uint64_t entries, size_t entry_len)
24
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
65
+int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
66
+ uint64_t entries, size_t entry_len,
67
+ int64_t max_size_bytes, const char *table_name,
68
+ Error **errp)
69
{
70
BDRVQcow2State *s = bs->opaque;
71
- uint64_t size;
72
73
- /* Use signed INT64_MAX as the maximum even for uint64_t header fields,
74
- * because values will be passed to qemu functions taking int64_t. */
75
- if (entries > INT64_MAX / entry_len) {
76
- return -EINVAL;
77
- }
78
-
79
- size = entries * entry_len;
80
-
81
- if (INT64_MAX - size < offset) {
82
- return -EINVAL;
83
+ if (entries > max_size_bytes / entry_len) {
84
+ error_setg(errp, "%s too large", table_name);
85
+ return -EFBIG;
86
}
25
}
87
26
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
88
- /* Tables must be cluster aligned */
27
bs->bl.pdiscard_alignment = s->cluster_size;
89
- if (offset_into_cluster(s, offset) != 0) {
90
+ /* Use signed INT64_MAX as the maximum even for uint64_t header fields,
91
+ * because values will be passed to qemu functions taking int64_t. */
92
+ if ((INT64_MAX - entries * entry_len < offset) ||
93
+ (offset_into_cluster(s, offset) != 0)) {
94
+ error_setg(errp, "%s offset invalid", table_name);
95
return -EINVAL;
96
}
97
98
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
99
s->refcount_table_size =
100
header.refcount_table_clusters << (s->cluster_bits - 3);
101
102
- if (header.refcount_table_clusters > qcow2_max_refcount_clusters(s)) {
103
- error_setg(errp, "Reference count table too large");
104
- ret = -EINVAL;
105
- goto fail;
106
- }
107
-
108
if (header.refcount_table_clusters == 0 && !(flags & BDRV_O_CHECK)) {
109
error_setg(errp, "Image does not contain a reference count table");
110
ret = -EINVAL;
111
goto fail;
112
}
113
114
- ret = validate_table_offset(bs, s->refcount_table_offset,
115
- s->refcount_table_size, sizeof(uint64_t));
116
+ ret = qcow2_validate_table(bs, s->refcount_table_offset,
117
+ header.refcount_table_clusters,
118
+ s->cluster_size, QCOW_MAX_REFTABLE_SIZE,
119
+ "Reference count table", errp);
120
if (ret < 0) {
121
- error_setg(errp, "Invalid reference count table offset");
122
goto fail;
123
}
124
125
- /* Snapshot table offset/length */
126
- if (header.nb_snapshots > QCOW_MAX_SNAPSHOTS) {
127
- error_setg(errp, "Too many snapshots");
128
- ret = -EINVAL;
129
- goto fail;
130
- }
131
-
132
- ret = validate_table_offset(bs, header.snapshots_offset,
133
- header.nb_snapshots,
134
- sizeof(QCowSnapshotHeader));
135
+ /* The total size in bytes of the snapshot table is checked in
136
+ * qcow2_read_snapshots() because the size of each snapshot is
137
+ * variable and we don't know it yet.
138
+ * Here we only check the offset and number of snapshots. */
139
+ ret = qcow2_validate_table(bs, header.snapshots_offset,
140
+ header.nb_snapshots,
141
+ sizeof(QCowSnapshotHeader),
142
+ sizeof(QCowSnapshotHeader) * QCOW_MAX_SNAPSHOTS,
143
+ "Snapshot table", errp);
144
if (ret < 0) {
145
- error_setg(errp, "Invalid snapshot table offset");
146
goto fail;
147
}
148
149
/* read the level 1 table */
150
- if (header.l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) {
151
- error_setg(errp, "Active L1 table too large");
152
- ret = -EFBIG;
153
+ ret = qcow2_validate_table(bs, header.l1_table_offset,
154
+ header.l1_size, sizeof(uint64_t),
155
+ QCOW_MAX_L1_SIZE, "Active L1 table", errp);
156
+ if (ret < 0) {
157
goto fail;
158
}
159
s->l1_size = header.l1_size;
160
+ s->l1_table_offset = header.l1_table_offset;
161
162
l1_vm_state_index = size_to_l1(s, header.size);
163
if (l1_vm_state_index > INT_MAX) {
164
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
165
goto fail;
166
}
167
168
- ret = validate_table_offset(bs, header.l1_table_offset,
169
- header.l1_size, sizeof(uint64_t));
170
- if (ret < 0) {
171
- error_setg(errp, "Invalid L1 table offset");
172
- goto fail;
173
- }
174
- s->l1_table_offset = header.l1_table_offset;
175
-
176
-
177
if (s->l1_size > 0) {
178
s->l1_table = qemu_try_blockalign(bs->file->bs,
179
ROUND_UP(s->l1_size * sizeof(uint64_t), 512));
180
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
181
index XXXXXXX..XXXXXXX 100644
182
--- a/tests/qemu-iotests/080.out
183
+++ b/tests/qemu-iotests/080.out
184
@@ -XXX,XX +XXX,XX @@ can't open device TEST_DIR/t.qcow2: Reference count table too large
185
186
== Misaligned refcount table ==
187
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
188
-can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
189
+can't open device TEST_DIR/t.qcow2: Reference count table offset invalid
190
191
== Huge refcount offset ==
192
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
193
-can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
194
+can't open device TEST_DIR/t.qcow2: Reference count table offset invalid
195
196
== Invalid snapshot table ==
197
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
198
-can't open device TEST_DIR/t.qcow2: Too many snapshots
199
-can't open device TEST_DIR/t.qcow2: Too many snapshots
200
-can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
201
-can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
202
+can't open device TEST_DIR/t.qcow2: Snapshot table too large
203
+can't open device TEST_DIR/t.qcow2: Snapshot table too large
204
+can't open device TEST_DIR/t.qcow2: Snapshot table offset invalid
205
+can't open device TEST_DIR/t.qcow2: Snapshot table offset invalid
206
207
== Hitting snapshot table size limit ==
208
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
209
@@ -XXX,XX +XXX,XX @@ read 512/512 bytes at offset 0
210
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
211
can't open device TEST_DIR/t.qcow2: Active L1 table too large
212
can't open device TEST_DIR/t.qcow2: Active L1 table too large
213
-can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
214
-can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
215
+can't open device TEST_DIR/t.qcow2: Active L1 table offset invalid
216
+can't open device TEST_DIR/t.qcow2: Active L1 table offset invalid
217
218
== Invalid L1 table (with internal snapshot in the image) ==
219
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
220
--
28
--
221
2.13.6
29
2.19.1
222
30
223
31
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Li Qiang <liq3ea@163.com>
2
2
3
It is called from qed_invalidate_cache in coroutine context (incoming
3
Signed-off-by: Li Qiang <liq3ea@163.com>
4
migration runs in a coroutine), so it's cleaner if metadata is always
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
loaded from a coroutine.
6
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-Id: <1516279431-30424-5-git-send-email-pbonzini@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
6
---
12
block/qed.c | 40 +++++++++++++++++++++++++++++++++++++---
7
include/sysemu/block-backend.h | 6 +++---
13
1 file changed, 37 insertions(+), 3 deletions(-)
8
block/block-backend.c | 8 ++++----
9
2 files changed, 7 insertions(+), 7 deletions(-)
14
10
15
diff --git a/block/qed.c b/block/qed.c
11
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qed.c
13
--- a/include/sysemu/block-backend.h
18
+++ b/block/qed.c
14
+++ b/include/sysemu/block-backend.h
19
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_init_state(BlockDriverState *bs)
15
@@ -XXX,XX +XXX,XX @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
20
qemu_co_queue_init(&s->allocating_write_reqs);
16
int error);
17
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
18
bool is_read, int error);
19
-int blk_is_read_only(BlockBackend *blk);
20
-int blk_is_sg(BlockBackend *blk);
21
-int blk_enable_write_cache(BlockBackend *blk);
22
+bool blk_is_read_only(BlockBackend *blk);
23
+bool blk_is_sg(BlockBackend *blk);
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
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-backend.c
31
+++ b/block/block-backend.c
32
@@ -XXX,XX +XXX,XX @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
33
}
21
}
34
}
22
35
23
-static int bdrv_qed_do_open(BlockDriverState *bs, QDict *options, int flags,
36
-int blk_is_read_only(BlockBackend *blk)
24
- Error **errp)
37
+bool blk_is_read_only(BlockBackend *blk)
25
+/* Called with table_lock held. */
26
+static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
27
+ int flags, Error **errp)
28
{
38
{
29
BDRVQEDState *s = bs->opaque;
39
BlockDriverState *bs = blk_bs(blk);
30
QEDHeader le_header;
40
31
@@ -XXX,XX +XXX,XX @@ out:
41
@@ -XXX,XX +XXX,XX @@ int blk_is_read_only(BlockBackend *blk)
32
return ret;
42
}
33
}
43
}
34
44
35
+typedef struct QEDOpenCo {
45
-int blk_is_sg(BlockBackend *blk)
36
+ BlockDriverState *bs;
46
+bool blk_is_sg(BlockBackend *blk)
37
+ QDict *options;
38
+ int flags;
39
+ Error **errp;
40
+ int ret;
41
+} QEDOpenCo;
42
+
43
+static void coroutine_fn bdrv_qed_open_entry(void *opaque)
44
+{
45
+ QEDOpenCo *qoc = opaque;
46
+ BDRVQEDState *s = qoc->bs->opaque;
47
+
48
+ qemu_co_mutex_lock(&s->table_lock);
49
+ qoc->ret = bdrv_qed_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
50
+ qemu_co_mutex_unlock(&s->table_lock);
51
+}
52
+
53
static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
54
Error **errp)
55
{
47
{
56
+ QEDOpenCo qoc = {
48
BlockDriverState *bs = blk_bs(blk);
57
+ .bs = bs,
49
58
+ .options = options,
50
if (!bs) {
59
+ .flags = flags,
51
- return 0;
60
+ .errp = errp,
52
+ return false;
61
+ .ret = -EINPROGRESS
62
+ };
63
+
64
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
65
false, errp);
66
if (!bs->file) {
67
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
68
}
53
}
69
54
70
bdrv_qed_init_state(bs);
55
return bdrv_is_sg(bs);
71
- return bdrv_qed_do_open(bs, options, flags, errp);
72
+ if (qemu_in_coroutine()) {
73
+ bdrv_qed_open_entry(&qoc);
74
+ } else {
75
+ qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
76
+ BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
77
+ }
78
+ BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
79
+ return qoc.ret;
80
}
56
}
81
57
82
static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
58
-int blk_enable_write_cache(BlockBackend *blk)
59
+bool blk_enable_write_cache(BlockBackend *blk)
60
{
61
return blk->enable_write_cache;
62
}
83
--
63
--
84
2.13.6
64
2.19.1
85
65
86
66
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Cleber Rosa <crosa@redhat.com>
2
2
3
QED's bdrv_invalidate_cache implementation would like to reuse functions
3
While testing the Python 3 changes which touch the 083 test, I noticed
4
that acquire/release the metadata locks. Call it from coroutine context
4
that it would fail with qcow2. Expanding the testing, I noticed it
5
to simplify the logic.
5
had nothing to do with the Python 3 changes, and in fact, it would not
6
pass on anything but raw:
6
7
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
raw: pass
8
Message-Id: <1516279431-30424-6-git-send-email-pbonzini@redhat.com>
9
bochs: not generic
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
cloop: not generic
11
parallels: fail
12
qcow: fail
13
qcow2: fail
14
qed: fail
15
vdi: fail
16
vhdx: fail
17
vmdk: fail
18
vpc: fail
19
luks: fail
20
21
The errors are a mixture I/O and "image not in xxx format", such as:
22
23
=== Check disconnect before data ===
24
25
Unexpected end-of-file before all bytes were read
26
-read failed: Input/output error
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
28
29
=== Check disconnect after data ===
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
40
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
41
---
12
include/block/block_int.h | 3 ++-
42
tests/qemu-iotests/083 | 2 +-
13
block.c | 41 +++++++++++++++++++++++++++++++++++++----
43
1 file changed, 1 insertion(+), 1 deletion(-)
14
block/iscsi.c | 6 +++---
15
block/nfs.c | 6 +++---
16
block/qcow2.c | 7 +++++--
17
block/qed.c | 13 +++++--------
18
block/rbd.c | 6 +++---
19
7 files changed, 58 insertions(+), 24 deletions(-)
20
44
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
45
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
22
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100755
23
--- a/include/block/block_int.h
47
--- a/tests/qemu-iotests/083
24
+++ b/include/block/block_int.h
48
+++ b/tests/qemu-iotests/083
25
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
26
/*
50
. ./common.rc
27
* Invalidate any cached meta-data.
51
. ./common.filter
28
*/
52
29
- void (*bdrv_invalidate_cache)(BlockDriverState *bs, Error **errp);
53
-_supported_fmt generic
30
+ void coroutine_fn (*bdrv_co_invalidate_cache)(BlockDriverState *bs,
54
+_supported_fmt raw
31
+ Error **errp);
55
_supported_proto nbd
32
int (*bdrv_inactivate)(BlockDriverState *bs);
56
_supported_os Linux
33
34
/*
35
diff --git a/block.c b/block.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block.c
38
+++ b/block.c
39
@@ -XXX,XX +XXX,XX @@ void bdrv_init_with_whitelist(void)
40
bdrv_init();
41
}
42
43
-void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
44
+static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
45
+ Error **errp)
46
{
47
BdrvChild *child, *parent;
48
uint64_t perm, shared_perm;
49
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
50
}
51
52
QLIST_FOREACH(child, &bs->children, next) {
53
- bdrv_invalidate_cache(child->bs, &local_err);
54
+ bdrv_co_invalidate_cache(child->bs, &local_err);
55
if (local_err) {
56
error_propagate(errp, local_err);
57
return;
58
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
59
}
60
bdrv_set_perm(bs, perm, shared_perm);
61
62
- if (bs->drv->bdrv_invalidate_cache) {
63
- bs->drv->bdrv_invalidate_cache(bs, &local_err);
64
+ if (bs->drv->bdrv_co_invalidate_cache) {
65
+ bs->drv->bdrv_co_invalidate_cache(bs, &local_err);
66
if (local_err) {
67
bs->open_flags |= BDRV_O_INACTIVE;
68
error_propagate(errp, local_err);
69
@@ -XXX,XX +XXX,XX @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
70
}
71
}
72
73
+typedef struct InvalidateCacheCo {
74
+ BlockDriverState *bs;
75
+ Error **errp;
76
+ bool done;
77
+} InvalidateCacheCo;
78
+
79
+static void coroutine_fn bdrv_invalidate_cache_co_entry(void *opaque)
80
+{
81
+ InvalidateCacheCo *ico = opaque;
82
+ bdrv_co_invalidate_cache(ico->bs, ico->errp);
83
+ ico->done = true;
84
+}
85
+
86
+void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
87
+{
88
+ Coroutine *co;
89
+ InvalidateCacheCo ico = {
90
+ .bs = bs,
91
+ .done = false,
92
+ .errp = errp
93
+ };
94
+
95
+ if (qemu_in_coroutine()) {
96
+ /* Fast-path if already in coroutine context */
97
+ bdrv_invalidate_cache_co_entry(&ico);
98
+ } else {
99
+ co = qemu_coroutine_create(bdrv_invalidate_cache_co_entry, &ico);
100
+ qemu_coroutine_enter(co);
101
+ BDRV_POLL_WHILE(bs, !ico.done);
102
+ }
103
+}
104
+
105
void bdrv_invalidate_cache_all(Error **errp)
106
{
107
BlockDriverState *bs;
108
diff --git a/block/iscsi.c b/block/iscsi.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/block/iscsi.c
111
+++ b/block/iscsi.c
112
@@ -XXX,XX +XXX,XX @@ static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
113
return 0;
114
}
115
116
-static void iscsi_invalidate_cache(BlockDriverState *bs,
117
- Error **errp)
118
+static void coroutine_fn iscsi_co_invalidate_cache(BlockDriverState *bs,
119
+ Error **errp)
120
{
121
IscsiLun *iscsilun = bs->opaque;
122
iscsi_allocmap_invalidate(iscsilun);
123
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
124
.create_opts = &iscsi_create_opts,
125
.bdrv_reopen_prepare = iscsi_reopen_prepare,
126
.bdrv_reopen_commit = iscsi_reopen_commit,
127
- .bdrv_invalidate_cache = iscsi_invalidate_cache,
128
+ .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache,
129
130
.bdrv_getlength = iscsi_getlength,
131
.bdrv_get_info = iscsi_get_info,
132
diff --git a/block/nfs.c b/block/nfs.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/block/nfs.c
135
+++ b/block/nfs.c
136
@@ -XXX,XX +XXX,XX @@ static void nfs_refresh_filename(BlockDriverState *bs, QDict *options)
137
}
138
139
#ifdef LIBNFS_FEATURE_PAGECACHE
140
-static void nfs_invalidate_cache(BlockDriverState *bs,
141
- Error **errp)
142
+static void coroutine_fn nfs_co_invalidate_cache(BlockDriverState *bs,
143
+ Error **errp)
144
{
145
NFSClient *client = bs->opaque;
146
nfs_pagecache_invalidate(client->context, client->fh);
147
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
148
.bdrv_refresh_filename = nfs_refresh_filename,
149
150
#ifdef LIBNFS_FEATURE_PAGECACHE
151
- .bdrv_invalidate_cache = nfs_invalidate_cache,
152
+ .bdrv_co_invalidate_cache = nfs_co_invalidate_cache,
153
#endif
154
};
155
156
diff --git a/block/qcow2.c b/block/qcow2.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/qcow2.c
159
+++ b/block/qcow2.c
160
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
161
qcow2_free_snapshots(bs);
162
}
163
164
-static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
165
+static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
166
+ Error **errp)
167
{
168
BDRVQcow2State *s = bs->opaque;
169
int flags = s->flags;
170
@@ -XXX,XX +XXX,XX @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
171
options = qdict_clone_shallow(bs->options);
172
173
flags &= ~BDRV_O_INACTIVE;
174
+ qemu_co_mutex_lock(&s->lock);
175
ret = qcow2_do_open(bs, options, flags, &local_err);
176
+ qemu_co_mutex_unlock(&s->lock);
177
QDECREF(options);
178
if (local_err) {
179
error_propagate(errp, local_err);
180
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
181
.bdrv_change_backing_file = qcow2_change_backing_file,
182
183
.bdrv_refresh_limits = qcow2_refresh_limits,
184
- .bdrv_invalidate_cache = qcow2_invalidate_cache,
185
+ .bdrv_co_invalidate_cache = qcow2_co_invalidate_cache,
186
.bdrv_inactivate = qcow2_inactivate,
187
188
.create_opts = &qcow2_create_opts,
189
diff --git a/block/qed.c b/block/qed.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/block/qed.c
192
+++ b/block/qed.c
193
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
194
return ret;
195
}
196
197
-static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
198
+static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
199
+ Error **errp)
200
{
201
BDRVQEDState *s = bs->opaque;
202
Error *local_err = NULL;
203
@@ -XXX,XX +XXX,XX @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
204
bdrv_qed_close(bs);
205
206
bdrv_qed_init_state(bs);
207
- if (qemu_in_coroutine()) {
208
- qemu_co_mutex_lock(&s->table_lock);
209
- }
210
+ qemu_co_mutex_lock(&s->table_lock);
211
ret = bdrv_qed_do_open(bs, NULL, bs->open_flags, &local_err);
212
- if (qemu_in_coroutine()) {
213
- qemu_co_mutex_unlock(&s->table_lock);
214
- }
215
+ qemu_co_mutex_unlock(&s->table_lock);
216
if (local_err) {
217
error_propagate(errp, local_err);
218
error_prepend(errp, "Could not reopen qed layer: ");
219
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
220
.bdrv_get_info = bdrv_qed_get_info,
221
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
222
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
223
- .bdrv_invalidate_cache = bdrv_qed_invalidate_cache,
224
+ .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
225
.bdrv_check = bdrv_qed_check,
226
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
227
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
228
diff --git a/block/rbd.c b/block/rbd.c
229
index XXXXXXX..XXXXXXX 100644
230
--- a/block/rbd.c
231
+++ b/block/rbd.c
232
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *qemu_rbd_aio_pdiscard(BlockDriverState *bs,
233
#endif
234
235
#ifdef LIBRBD_SUPPORTS_INVALIDATE
236
-static void qemu_rbd_invalidate_cache(BlockDriverState *bs,
237
- Error **errp)
238
+static void coroutine_fn qemu_rbd_co_invalidate_cache(BlockDriverState *bs,
239
+ Error **errp)
240
{
241
BDRVRBDState *s = bs->opaque;
242
int r = rbd_invalidate_cache(s->image);
243
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
244
.bdrv_snapshot_list = qemu_rbd_snap_list,
245
.bdrv_snapshot_goto = qemu_rbd_snap_rollback,
246
#ifdef LIBRBD_SUPPORTS_INVALIDATE
247
- .bdrv_invalidate_cache = qemu_rbd_invalidate_cache,
248
+ .bdrv_co_invalidate_cache = qemu_rbd_co_invalidate_cache,
249
#endif
250
};
251
57
252
--
58
--
253
2.13.6
59
2.19.1
254
60
255
61
diff view generated by jsdifflib
1
Move the parsing of the QDict options up to the callers, in preparation
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
for the .bdrv_co_create implementation that directly gets a QAPI type.
2
Reviewed-by: Alberto Garcia <berto@igalia.com>
3
---
4
block/vpc.c | 2 ++
5
1 file changed, 2 insertions(+)
3
6
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
diff --git a/block/vpc.c b/block/vpc.c
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
block/ssh.c | 34 +++++++++++++++++++++-------------
8
1 file changed, 21 insertions(+), 13 deletions(-)
9
10
diff --git a/block/ssh.c b/block/ssh.c
11
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
12
--- a/block/ssh.c
9
--- a/block/vpc.c
13
+++ b/block/ssh.c
10
+++ b/block/vpc.c
14
@@ -XXX,XX +XXX,XX @@ fail:
11
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
15
return result;
16
}
17
18
-static int connect_to_ssh(BDRVSSHState *s, QDict *options,
19
+static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts,
20
int ssh_flags, int creat_mode, Error **errp)
21
{
22
- BlockdevOptionsSsh *opts;
23
int r, ret;
24
const char *user;
25
long port = 0;
26
27
- opts = ssh_parse_options(options, errp);
28
- if (opts == NULL) {
29
- return -EINVAL;
30
- }
31
-
32
if (opts->has_user) {
33
user = opts->user;
34
} else {
35
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
36
goto err;
37
}
12
}
38
13
39
- qapi_free_BlockdevOptionsSsh(opts);
14
qemu_co_mutex_init(&s->lock);
40
-
15
+ qemu_opts_del(opts);
41
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
16
42
if (r < 0) {
43
sftp_error_setg(errp, s, "failed to read file attributes");
44
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
45
}
46
s->session = NULL;
47
48
- qapi_free_BlockdevOptionsSsh(opts);
49
-
50
return ret;
51
}
52
53
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
54
Error **errp)
55
{
56
BDRVSSHState *s = bs->opaque;
57
+ BlockdevOptionsSsh *opts;
58
int ret;
59
int ssh_flags;
60
61
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
62
ssh_flags |= LIBSSH2_FXF_WRITE;
63
}
64
65
+ opts = ssh_parse_options(options, errp);
66
+ if (opts == NULL) {
67
+ return -EINVAL;
68
+ }
69
+
70
/* Start up SSH. */
71
- ret = connect_to_ssh(s, options, ssh_flags, 0, errp);
72
+ ret = connect_to_ssh(s, opts, ssh_flags, 0, errp);
73
if (ret < 0) {
74
goto err;
75
}
76
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
77
/* Go non-blocking. */
78
libssh2_session_set_blocking(s->session, 0);
79
80
+ qapi_free_BlockdevOptionsSsh(opts);
81
+
82
return 0;
17
return 0;
83
18
84
err:
19
fail:
85
@@ -XXX,XX +XXX,XX @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags,
20
+ qemu_opts_del(opts);
86
}
21
qemu_vfree(s->pagetable);
87
s->sock = -1;
22
#ifdef CACHE
88
23
g_free(s->pageentry_u8);
89
+ qapi_free_BlockdevOptionsSsh(opts);
90
+
91
return ret;
92
}
93
94
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
95
int r, ret;
96
int64_t total_size = 0;
97
QDict *uri_options = NULL;
98
+ BlockdevOptionsSsh *ssh_opts = NULL;
99
BDRVSSHState s;
100
101
ssh_state_init(&s);
102
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
103
goto out;
104
}
105
106
- r = connect_to_ssh(&s, uri_options,
107
+ ssh_opts = ssh_parse_options(uri_options, errp);
108
+ if (ssh_opts == NULL) {
109
+ ret = -EINVAL;
110
+ goto out;
111
+ }
112
+
113
+ r = connect_to_ssh(&s, ssh_opts,
114
LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
115
LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
116
0644, errp);
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
118
if (uri_options != NULL) {
119
QDECREF(uri_options);
120
}
121
+ qapi_free_BlockdevOptionsSsh(ssh_opts);
122
return ret;
123
}
124
125
--
24
--
126
2.13.6
25
2.19.1
127
26
128
27
diff view generated by jsdifflib
1
Create a BlockdevOptionsSsh object in connect_to_ssh() and take the
1
From: Peter Maydell <peter.maydell@linaro.org>
2
options from there. 'host_key_check' is still processed separately
2
3
because it's not in the schema yet.
3
Taking the address of a field in a packed struct is a bad idea, because
4
4
it might not be actually aligned enough for that pointer type (and
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
9
There are a few places where the in-place swap function is
10
used on something other than a packed struct field; we convert
11
those anyway, for consistency.
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
18
---
8
block/ssh.c | 137 +++++++++++++++++++++++++++---------------------------------
19
block/vhdx.h | 12 ++---
9
1 file changed, 62 insertions(+), 75 deletions(-)
20
block/vhdx-endian.c | 118 ++++++++++++++++++++++----------------------
10
21
block/vhdx-log.c | 4 +-
11
diff --git a/block/ssh.c b/block/ssh.c
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
12
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
13
--- a/block/ssh.c
27
--- a/block/vhdx.h
14
+++ b/block/ssh.c
28
+++ b/block/vhdx.h
15
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
16
#include "qemu/sockets.h"
30
17
#include "qemu/uri.h"
31
static inline void leguid_to_cpus(MSGUID *guid)
18
#include "qapi/qapi-visit-sockets.h"
32
{
19
+#include "qapi/qapi-visit-block-core.h"
33
- le32_to_cpus(&guid->data1);
20
#include "qapi/qmp/qdict.h"
34
- le16_to_cpus(&guid->data2);
21
#include "qapi/qmp/qstring.h"
35
- le16_to_cpus(&guid->data3);
22
#include "qapi/qobject-input-visitor.h"
36
+ guid->data1 = le32_to_cpu(guid->data1);
23
@@ -XXX,XX +XXX,XX @@ static QemuOptsList ssh_runtime_opts = {
37
+ guid->data2 = le16_to_cpu(guid->data2);
24
.type = QEMU_OPT_NUMBER,
38
+ guid->data3 = le16_to_cpu(guid->data3);
25
.help = "Port to connect to",
39
}
26
},
40
27
- {
41
static inline void cpu_to_leguids(MSGUID *guid)
28
- .name = "path",
42
{
29
- .type = QEMU_OPT_STRING,
43
- cpu_to_le32s(&guid->data1);
30
- .help = "Path of the image on the host",
44
- cpu_to_le16s(&guid->data2);
31
- },
45
- cpu_to_le16s(&guid->data3);
32
- {
46
+ guid->data1 = cpu_to_le32(guid->data1);
33
- .name = "user",
47
+ guid->data2 = cpu_to_le16(guid->data2);
34
- .type = QEMU_OPT_STRING,
48
+ guid->data3 = cpu_to_le16(guid->data3);
35
- .help = "User as which to connect",
49
}
36
- },
50
37
- {
51
void vhdx_header_le_import(VHDXHeader *h);
38
- .name = "host_key_check",
52
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
39
- .type = QEMU_OPT_STRING,
53
index XXXXXXX..XXXXXXX 100644
40
- .help = "Defines how and what to check the host key against",
54
--- a/block/vhdx-endian.c
41
- },
55
+++ b/block/vhdx-endian.c
42
{ /* end of list */ }
56
@@ -XXX,XX +XXX,XX @@ void vhdx_header_le_import(VHDXHeader *h)
43
},
57
{
44
};
58
assert(h != NULL);
45
@@ -XXX,XX +XXX,XX @@ static bool ssh_process_legacy_socket_options(QDict *output_opts,
59
46
return true;
60
- le32_to_cpus(&h->signature);
47
}
61
- le32_to_cpus(&h->checksum);
48
62
- le64_to_cpus(&h->sequence_number);
49
-static InetSocketAddress *ssh_config(QDict *options, Error **errp)
63
+ h->signature = le32_to_cpu(h->signature);
50
+static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp)
64
+ h->checksum = le32_to_cpu(h->checksum);
51
{
65
+ h->sequence_number = le64_to_cpu(h->sequence_number);
52
- InetSocketAddress *inet = NULL;
66
53
- QDict *addr = NULL;
67
leguid_to_cpus(&h->file_write_guid);
54
- QObject *crumpled_addr = NULL;
68
leguid_to_cpus(&h->data_write_guid);
55
- Visitor *iv = NULL;
69
leguid_to_cpus(&h->log_guid);
56
- Error *local_error = NULL;
70
57
-
71
- le16_to_cpus(&h->log_version);
58
- qdict_extract_subqdict(options, &addr, "server.");
72
- le16_to_cpus(&h->version);
59
- if (!qdict_size(addr)) {
73
- le32_to_cpus(&h->log_length);
60
- error_setg(errp, "SSH server address missing");
74
- le64_to_cpus(&h->log_offset);
61
- goto out;
75
+ h->log_version = le16_to_cpu(h->log_version);
62
+ BlockdevOptionsSsh *result = NULL;
76
+ h->version = le16_to_cpu(h->version);
63
+ QemuOpts *opts = NULL;
77
+ h->log_length = le32_to_cpu(h->log_length);
64
+ Error *local_err = NULL;
78
+ h->log_offset = le64_to_cpu(h->log_offset);
65
+ QObject *crumpled;
79
}
66
+ const QDictEntry *e;
80
67
+ Visitor *v;
81
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
68
+
82
@@ -XXX,XX +XXX,XX @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
69
+ /* Translate legacy options */
83
{
70
+ opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort);
84
assert(d != NULL);
71
+ qemu_opts_absorb_qdict(opts, options, &local_err);
85
72
+ if (local_err) {
86
- le32_to_cpus(&d->signature);
73
+ error_propagate(errp, local_err);
87
- le64_to_cpus(&d->file_offset);
74
+ goto fail;
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;
75
}
309
}
76
310
77
- crumpled_addr = qdict_crumple(addr, errp);
311
- le32_to_cpus(&s->params.block_size);
78
- if (!crumpled_addr) {
312
- le32_to_cpus(&s->params.data_bits);
79
- goto out;
313
+ s->params.block_size = le32_to_cpu(s->params.block_size);
80
+ if (!ssh_process_legacy_socket_options(options, opts, errp)) {
314
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
81
+ goto fail;
315
82
+ }
316
83
+
317
/* We now have the file parameters, so we can tell if this is a
84
+ /* Create the QAPI object */
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
85
+ crumpled = qdict_crumple(options, errp);
319
goto exit;
86
+ if (crumpled == NULL) {
87
+ goto fail;
88
}
320
}
89
321
90
/*
322
- le64_to_cpus(&s->virtual_disk_size);
91
@@ -XXX,XX +XXX,XX @@ static InetSocketAddress *ssh_config(QDict *options, Error **errp)
323
- le32_to_cpus(&s->logical_sector_size);
92
* but when they come from -drive, they're all QString. The
324
- le32_to_cpus(&s->physical_sector_size);
93
* visitor expects the former.
325
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
94
*/
326
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
95
- iv = qobject_input_visitor_new(crumpled_addr);
327
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
96
- visit_type_InetSocketAddress(iv, NULL, &inet, &local_error);
328
97
- if (local_error) {
329
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
98
- error_propagate(errp, local_error);
330
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
99
- goto out;
331
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
100
+ v = qobject_input_visitor_new(crumpled);
332
/* endian convert, and verify populated BAT field file offsets against
101
+ visit_type_BlockdevOptionsSsh(v, NULL, &result, &local_err);
333
* region table and log entries */
102
+ visit_free(v);
334
for (i = 0; i < s->bat_entries; i++) {
103
+ qobject_decref(crumpled);
335
- le64_to_cpus(&s->bat[i]);
104
+
336
+ s->bat[i] = le64_to_cpu(s->bat[i]);
105
+ if (local_err) {
337
if (payblocks--) {
106
+ error_propagate(errp, local_err);
338
/* payload bat entries */
107
+ goto fail;
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);
108
}
346
}
109
347
110
-out:
348
vhdx_guid_generate(&mt_page83->page_83_data);
111
- QDECREF(addr);
349
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
112
- qobject_decref(crumpled_addr);
350
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
113
- visit_free(iv);
351
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
114
- return inet;
352
block_state);
115
+ /* Remove the processed options from the QDict (the visitor processes
353
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
116
+ * _all_ options in the QDict) */
354
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
117
+ while ((e = qdict_first(options))) {
355
sector_num += s->sectors_per_block;
118
+ qdict_del(options, e->key);
119
+ }
120
+
121
+fail:
122
+ qemu_opts_del(opts);
123
+ return result;
124
}
125
126
static int connect_to_ssh(BDRVSSHState *s, QDict *options,
127
int ssh_flags, int creat_mode, Error **errp)
128
{
129
+ BlockdevOptionsSsh *opts;
130
int r, ret;
131
- QemuOpts *opts = NULL;
132
- Error *local_err = NULL;
133
- const char *user, *path, *host_key_check;
134
+ const char *user, *host_key_check;
135
long port = 0;
136
137
- opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort);
138
- qemu_opts_absorb_qdict(opts, options, &local_err);
139
- if (local_err) {
140
- ret = -EINVAL;
141
- error_propagate(errp, local_err);
142
- goto err;
143
- }
144
-
145
- if (!ssh_process_legacy_socket_options(options, opts, errp)) {
146
- ret = -EINVAL;
147
- goto err;
148
+ host_key_check = qdict_get_try_str(options, "host_key_check");
149
+ if (!host_key_check) {
150
+ host_key_check = "yes";
151
+ } else {
152
+ qdict_del(options, "host_key_check");
153
}
154
155
- path = qemu_opt_get(opts, "path");
156
- if (!path) {
157
- ret = -EINVAL;
158
- error_setg(errp, "No path was specified");
159
- goto err;
160
+ opts = ssh_parse_options(options, errp);
161
+ if (opts == NULL) {
162
+ return -EINVAL;
163
}
164
165
- user = qemu_opt_get(opts, "user");
166
- if (!user) {
167
+ if (opts->has_user) {
168
+ user = opts->user;
169
+ } else {
170
user = g_get_user_name();
171
if (!user) {
172
error_setg_errno(errp, errno, "Can't get user name");
173
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
174
}
356
}
175
}
357
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
176
177
- host_key_check = qemu_opt_get(opts, "host_key_check");
178
- if (!host_key_check) {
179
- host_key_check = "yes";
180
- }
181
-
182
/* Pop the config into our state object, Exit if invalid */
183
- s->inet = ssh_config(options, errp);
184
- if (!s->inet) {
185
- ret = -EINVAL;
186
- goto err;
187
- }
188
+ s->inet = opts->server;
189
+ opts->server = NULL;
190
191
if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) {
192
error_setg(errp, "Use only numeric port value");
193
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
194
195
/* Open the remote file. */
196
DPRINTF("opening file %s flags=0x%x creat_mode=0%o",
197
- path, ssh_flags, creat_mode);
198
- s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode);
199
+ opts->path, ssh_flags, creat_mode);
200
+ s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags,
201
+ creat_mode);
202
if (!s->sftp_handle) {
203
- session_error_setg(errp, s, "failed to open remote file '%s'", path);
204
+ session_error_setg(errp, s, "failed to open remote file '%s'",
205
+ opts->path);
206
ret = -EINVAL;
207
goto err;
208
}
209
210
- qemu_opts_del(opts);
211
+ qapi_free_BlockdevOptionsSsh(opts);
212
213
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
214
if (r < 0) {
215
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
216
}
217
s->session = NULL;
218
219
- qemu_opts_del(opts);
220
+ qapi_free_BlockdevOptionsSsh(opts);
221
222
return ret;
223
}
224
--
358
--
225
2.13.6
359
2.19.1
226
360
227
361
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Peter Maydell <peter.maydell@linaro.org>
2
2
3
The AFL image is to exercise the code validating image size, which
3
Taking the address of a field in a packed struct is a bad idea, because
4
doesn't work on 32 bit or when out of memory (there is a large
4
it might not be actually aligned enough for that pointer type (and
5
allocation before the interesting point). So check that and skip the
5
thus cause a crash on dereference on some host architectures). Newer
6
test, instead of faking the result.
6
versions of clang warn about this. Avoid the bug by not using the
7
"modify in place" byte swapping functions.
7
8
8
Signed-off-by: Fam Zheng <famz@redhat.com>
9
There are a few places where the in-place swap function is
9
Message-id: 20180301011413.11531-1-famz@redhat.com
10
used on something other than a packed struct field; we convert
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
those anyway, for consistency.
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
13
Patch produced with scripts/coccinelle/inplace-byteswaps.cocci.
14
15
There are other places where we take the address of a packed member
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>
12
---
22
---
13
tests/qemu-iotests/059 | 5 ++---
23
block/vdi.c | 64 ++++++++++++++++++++++++++---------------------------
14
1 file changed, 2 insertions(+), 3 deletions(-)
24
1 file changed, 32 insertions(+), 32 deletions(-)
15
25
16
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
26
diff --git a/block/vdi.c b/block/vdi.c
17
index XXXXXXX..XXXXXXX 100755
27
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/059
28
--- a/block/vdi.c
19
+++ b/tests/qemu-iotests/059
29
+++ b/block/vdi.c
20
@@ -XXX,XX +XXX,XX @@ done
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
echo
31
22
echo "=== Testing afl image with a very large capacity ==="
32
static void vdi_header_to_cpu(VdiHeader *header)
23
_use_sample_img afl9.vmdk.bz2
33
{
24
-# The sed makes this test pass on machines with little RAM
34
- le32_to_cpus(&header->signature);
25
-# (and also with 32 bit builds)
35
- le32_to_cpus(&header->version);
26
-_img_info | sed -e 's/Cannot allocate memory/Invalid argument/'
36
- le32_to_cpus(&header->header_size);
27
+_img_info | grep -q 'Cannot allocate memory' && _notrun "Insufficent memory, skipped test"
37
- le32_to_cpus(&header->image_type);
28
+_img_info
38
- le32_to_cpus(&header->image_flags);
29
_cleanup_test_img
39
- le32_to_cpus(&header->offset_bmap);
30
40
- le32_to_cpus(&header->offset_data);
31
# success, all done
41
- le32_to_cpus(&header->cylinders);
42
- le32_to_cpus(&header->heads);
43
- le32_to_cpus(&header->sectors);
44
- le32_to_cpus(&header->sector_size);
45
- le64_to_cpus(&header->disk_size);
46
- le32_to_cpus(&header->block_size);
47
- le32_to_cpus(&header->block_extra);
48
- le32_to_cpus(&header->blocks_in_image);
49
- le32_to_cpus(&header->blocks_allocated);
50
+ header->signature = le32_to_cpu(header->signature);
51
+ header->version = le32_to_cpu(header->version);
52
+ header->header_size = le32_to_cpu(header->header_size);
53
+ header->image_type = le32_to_cpu(header->image_type);
54
+ header->image_flags = le32_to_cpu(header->image_flags);
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);
32
--
108
--
33
2.13.6
109
2.19.1
34
110
35
111
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
'qemu-img check' cannot detect if a snapshot's L1 table is corrupted.
3
This is a static function with only one caller, so there's no need to
4
This patch checks the table's offset and size and reports corruption
4
keep it. Inlining the code in quorum_compare() makes it much simpler.
5
if the values are not valid.
6
7
This patch doesn't add code to fix that corruption yet, only to detect
8
and report it.
9
5
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reported-by: Markus Armbruster <armbru@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
9
---
14
block/qcow2-refcount.c | 14 ++++++++++++++
10
block/quorum.c | 24 +++++-------------------
15
tests/qemu-iotests/080 | 2 ++
11
1 file changed, 5 insertions(+), 19 deletions(-)
16
tests/qemu-iotests/080.out | 20 ++++++++++++++++++++
17
3 files changed, 36 insertions(+)
18
12
19
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
13
diff --git a/block/quorum.c b/block/quorum.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2-refcount.c
15
--- a/block/quorum.c
22
+++ b/block/qcow2-refcount.c
16
+++ b/block/quorum.c
23
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
17
@@ -XXX,XX +XXX,XX @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
24
/* snapshots */
18
return true;
25
for (i = 0; i < s->nb_snapshots; i++) {
19
}
26
sn = s->snapshots + i;
20
27
+ if (offset_into_cluster(s, sn->l1_table_offset)) {
21
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
28
+ fprintf(stderr, "ERROR snapshot %s (%s) l1_offset=%#" PRIx64 ": "
22
- const char *fmt, ...)
29
+ "L1 table is not cluster aligned; snapshot table entry "
23
-{
30
+ "corrupted\n", sn->id_str, sn->name, sn->l1_table_offset);
24
- va_list ap;
31
+ res->corruptions++;
25
-
32
+ continue;
26
- va_start(ap, fmt);
33
+ }
27
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
34
+ if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) {
28
- acb->offset, acb->bytes);
35
+ fprintf(stderr, "ERROR snapshot %s (%s) l1_size=%#" PRIx32 ": "
29
- vfprintf(stderr, fmt, ap);
36
+ "L1 table is too large; snapshot table entry corrupted\n",
30
- fprintf(stderr, "\n");
37
+ sn->id_str, sn->name, sn->l1_size);
31
- va_end(ap);
38
+ res->corruptions++;
32
- exit(1);
39
+ continue;
33
-}
40
+ }
34
-
41
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
35
-static bool quorum_compare(QuorumAIOCB *acb,
42
sn->l1_table_offset, sn->l1_size, 0, fix);
36
- QEMUIOVector *a,
43
if (ret < 0) {
37
- QEMUIOVector *b)
44
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
38
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
45
index XXXXXXX..XXXXXXX 100755
39
{
46
--- a/tests/qemu-iotests/080
40
BDRVQuorumState *s = acb->bs->opaque;
47
+++ b/tests/qemu-iotests/080
41
ssize_t offset;
48
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x0
42
@@ -XXX,XX +XXX,XX @@ static bool quorum_compare(QuorumAIOCB *acb,
49
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
43
if (s->is_blkverify) {
50
{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
44
offset = qemu_iovec_compare(a, b);
51
{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir
45
if (offset != -1) {
52
+_check_test_img
46
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
53
47
- acb->offset + offset);
54
echo
48
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
55
echo "== Invalid snapshot L1 table size =="
49
+ " contents mismatch at offset %" PRIu64 "\n",
56
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
50
+ acb->offset, acb->bytes, acb->offset + offset);
57
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
51
+ exit(1);
58
{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
52
}
59
{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir
53
return true;
60
+_check_test_img
54
}
61
62
# success, all done
63
echo "*** done"
64
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
65
index XXXXXXX..XXXXXXX 100644
66
--- a/tests/qemu-iotests/080.out
67
+++ b/tests/qemu-iotests/080.out
68
@@ -XXX,XX +XXX,XX @@ write failed: Invalid argument
69
qemu-img: Snapshot L1 table offset invalid
70
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invalid argument
71
qemu-img: Could not delete snapshot 'test': Snapshot L1 table offset invalid
72
+ERROR snapshot 1 (test) l1_offset=0x400200: L1 table is not cluster aligned; snapshot table entry corrupted
73
+Leaked cluster 4 refcount=2 reference=1
74
+Leaked cluster 5 refcount=2 reference=1
75
+Leaked cluster 6 refcount=1 reference=0
76
+
77
+1 errors were found on the image.
78
+Data may be corrupted, or further writes to the image may corrupt it.
79
+
80
+3 leaked clusters were found on the image.
81
+This means waste of disk space, but no harm to data.
82
83
== Invalid snapshot L1 table size ==
84
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
85
@@ -XXX,XX +XXX,XX @@ write failed: File too large
86
qemu-img: Snapshot L1 table too large
87
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File too large
88
qemu-img: Could not delete snapshot 'test': Snapshot L1 table too large
89
+ERROR snapshot 1 (test) l1_size=0x10000000: L1 table is too large; snapshot table entry corrupted
90
+Leaked cluster 4 refcount=2 reference=1
91
+Leaked cluster 5 refcount=2 reference=1
92
+Leaked cluster 6 refcount=1 reference=0
93
+
94
+1 errors were found on the image.
95
+Data may be corrupted, or further writes to the image may corrupt it.
96
+
97
+3 leaked clusters were found on the image.
98
+This means waste of disk space, but no harm to data.
99
*** done
100
--
55
--
101
2.13.6
56
2.19.1
102
57
103
58
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
The inactive-l2 overlap check iterates uses the L1 tables from all
3
The blkverify mode of Quorum can only be enabled if the number of
4
snapshots, but it does not validate them first.
4
children is exactly two and the value of vote-threshold is also two.
5
5
6
We now have a function to take care of this, so let's use it.
6
If the user tries to enable it but the other settings are incorrect
7
then QEMU simply prints an error message to stderr and carries on
8
disabling the blkverify setting.
9
10
This patch makes quorum_open() fail and return an error in this case.
7
11
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reported-by: Markus Armbruster <armbru@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
15
---
12
block/qcow2-refcount.c | 10 +++++++++-
16
block/quorum.c | 13 ++++++-------
13
tests/qemu-iotests/080 | 4 ++++
17
1 file changed, 6 insertions(+), 7 deletions(-)
14
tests/qemu-iotests/080.out | 4 ++++
15
3 files changed, 17 insertions(+), 1 deletion(-)
16
18
17
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
19
diff --git a/block/quorum.c b/block/quorum.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-refcount.c
21
--- a/block/quorum.c
20
+++ b/block/qcow2-refcount.c
22
+++ b/block/quorum.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
23
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
22
uint64_t l1_ofs = s->snapshots[i].l1_table_offset;
24
s->read_pattern = ret;
23
uint32_t l1_sz = s->snapshots[i].l1_size;
25
24
uint64_t l1_sz2 = l1_sz * sizeof(uint64_t);
26
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
25
- uint64_t *l1 = g_try_malloc(l1_sz2);
27
- /* is the driver in blkverify mode */
26
+ uint64_t *l1;
28
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
27
int ret;
29
- s->num_children == 2 && s->threshold == 2) {
28
30
- s->is_blkverify = true;
29
+ ret = qcow2_validate_table(bs, l1_ofs, l1_sz, sizeof(uint64_t),
31
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
30
+ QCOW_MAX_L1_SIZE, "", NULL);
32
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
31
+ if (ret < 0) {
33
- "and using two files with vote_threshold=2\n");
32
+ return ret;
34
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
33
+ }
35
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
34
+
36
+ error_setg(&local_err, "blkverify=on can only be set if there are "
35
+ l1 = g_try_malloc(l1_sz2);
37
+ "exactly two files and vote-threshold is 2");
36
+
38
+ ret = -EINVAL;
37
if (l1_sz2 && l1 == NULL) {
39
+ goto exit;
38
return -ENOMEM;
40
}
39
}
41
40
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
42
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
41
index XXXXXXX..XXXXXXX 100755
42
--- a/tests/qemu-iotests/080
43
+++ b/tests/qemu-iotests/080
44
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
45
poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x00"
46
{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
47
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
48
+{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
49
+ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
50
51
echo
52
echo "== Invalid snapshot L1 table size =="
53
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
54
poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
55
{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
56
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
57
+{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
58
+ -c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
59
60
# success, all done
61
echo "*** done"
62
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/080.out
65
+++ b/tests/qemu-iotests/080.out
66
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 0
67
qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid
68
qemu-img: Snapshot L1 table offset invalid
69
qemu-img: Error while amending options: Invalid argument
70
+Failed to flush the refcount block cache: Invalid argument
71
+write failed: Invalid argument
72
73
== Invalid snapshot L1 table size ==
74
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
75
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 0
76
qemu-img: Failed to load snapshot: Snapshot L1 table too large
77
qemu-img: Snapshot L1 table too large
78
qemu-img: Error while amending options: File too large
79
+Failed to flush the refcount block cache: File too large
80
+write failed: File too large
81
*** done
82
--
43
--
83
2.13.6
44
2.19.1
84
45
85
46
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This function copies a snapshot's L1 table into the active one without
4
validating it first.
5
6
We now have a function to take care of this, so let's use it.
7
8
Cc: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
5
---
13
block/qcow2-snapshot.c | 9 +++++++++
6
tests/qemu-iotests/081 | 30 ++++++++++++++++++++++++++++++
14
tests/qemu-iotests/080 | 2 ++
7
tests/qemu-iotests/081.out | 16 ++++++++++++++++
15
tests/qemu-iotests/080.out | 4 ++++
8
2 files changed, 46 insertions(+)
16
3 files changed, 15 insertions(+)
17
9
18
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
10
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
19
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100755
20
--- a/block/qcow2-snapshot.c
12
--- a/tests/qemu-iotests/081
21
+++ b/block/qcow2-snapshot.c
13
+++ b/tests/qemu-iotests/081
22
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
14
@@ -XXX,XX +XXX,XX @@ echo "== checking that quorum is broken =="
23
{
15
24
BDRVQcow2State *s = bs->opaque;
16
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
25
QCowSnapshot *sn;
17
26
+ Error *local_err = NULL;
18
+echo
27
int i, snapshot_index;
19
+echo "== checking the blkverify mode with broken content =="
28
int cur_l1_bytes, sn_l1_bytes;
29
int ret;
30
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
31
}
32
sn = &s->snapshots[snapshot_index];
33
34
+ ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
35
+ sizeof(uint64_t), QCOW_MAX_L1_SIZE,
36
+ "Snapshot L1 table", &local_err);
37
+ if (ret < 0) {
38
+ error_report_err(local_err);
39
+ goto fail;
40
+ }
41
+
20
+
42
if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
21
+quorum="driver=raw,file.driver=quorum,file.vote-threshold=2,file.blkverify=on"
43
error_report("qcow2: Loading snapshots with different disk "
22
+quorum="$quorum,file.children.0.file.filename=$TEST_DIR/1.raw"
44
"size is not implemented");
23
+quorum="$quorum,file.children.1.file.filename=$TEST_DIR/2.raw"
45
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
24
+quorum="$quorum,file.children.0.driver=raw"
46
index XXXXXXX..XXXXXXX 100755
25
+quorum="$quorum,file.children.1.driver=raw"
47
--- a/tests/qemu-iotests/080
26
+
48
+++ b/tests/qemu-iotests/080
27
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
49
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x0
28
+
50
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
29
+echo
51
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
30
+echo "== writing the same data to both files =="
52
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
31
+
53
+{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
32
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
54
33
+$QEMU_IO -c "write -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
55
echo
34
+
56
echo "== Invalid snapshot L1 table size =="
35
+echo
57
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
36
+echo "== checking the blkverify mode with valid content =="
58
{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
37
+
59
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
38
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
60
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
39
+
61
+{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
40
+echo
62
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
+
63
# success, all done
48
# success, all done
64
echo "*** done"
49
echo "*** done"
65
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
50
rm -f $seq.full
51
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
66
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
67
--- a/tests/qemu-iotests/080.out
53
--- a/tests/qemu-iotests/081.out
68
+++ b/tests/qemu-iotests/080.out
54
+++ b/tests/qemu-iotests/081.out
69
@@ -XXX,XX +XXX,XX @@ qemu-img: Snapshot L1 table offset invalid
55
@@ -XXX,XX +XXX,XX @@ wrote 10485760/10485760 bytes at offset 0
70
qemu-img: Error while amending options: Invalid argument
56
71
Failed to flush the refcount block cache: Invalid argument
57
== checking that quorum is broken ==
72
write failed: Invalid argument
58
read failed: Input/output error
73
+qemu-img: Snapshot L1 table offset invalid
59
+
74
+qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invalid argument
60
+== checking the blkverify mode with broken content ==
75
61
+quorum: offset=0 bytes=10485760 contents mismatch at offset 0
76
== Invalid snapshot L1 table size ==
62
+
77
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
63
+== writing the same data to both files ==
78
@@ -XXX,XX +XXX,XX @@ qemu-img: Snapshot L1 table too large
64
+wrote 10485760/10485760 bytes at offset 0
79
qemu-img: Error while amending options: File too large
65
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
80
Failed to flush the refcount block cache: File too large
66
+wrote 10485760/10485760 bytes at offset 0
81
write failed: File too large
67
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
82
+qemu-img: Snapshot L1 table too large
68
+
83
+qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File too large
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
84
*** done
75
*** done
85
--
76
--
86
2.13.6
77
2.19.1
87
78
88
79
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
This function deletes a snapshot from disk, removing its entry from
3
The blkverify mode of Quorum only works when the number of children is
4
the snapshot table, freeing its L1 table and decreasing the refcounts
4
exactly two, so any attempt to add a new one must return an error.
5
of all clusters.
6
5
7
The L1 table offset and size are however not validated. If we use
6
quorum_del_child() on the other hand doesn't need any additional check
8
invalid values in this function we'll probably corrupt the image even
7
because decreasing the number of children would make it go under the
9
more, so we should return an error instead.
8
vote threshold.
10
11
We now have a function to take care of this, so let's use it.
12
9
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reported-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
13
---
17
block/qcow2-snapshot.c | 7 +++++++
14
block/quorum.c | 8 ++++++++
18
tests/qemu-iotests/080 | 2 ++
15
1 file changed, 8 insertions(+)
19
tests/qemu-iotests/080.out | 2 ++
20
3 files changed, 11 insertions(+)
21
16
22
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
17
diff --git a/block/quorum.c b/block/quorum.c
23
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-snapshot.c
19
--- a/block/quorum.c
25
+++ b/block/qcow2-snapshot.c
20
+++ b/block/quorum.c
26
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_delete(BlockDriverState *bs,
21
@@ -XXX,XX +XXX,XX @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
27
}
22
char indexstr[32];
28
sn = s->snapshots[snapshot_index];
23
int ret;
29
24
30
+ ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size,
25
+ if (s->is_blkverify) {
31
+ sizeof(uint64_t), QCOW_MAX_L1_SIZE,
26
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
32
+ "Snapshot L1 table", errp);
27
+ return;
33
+ if (ret < 0) {
34
+ return ret;
35
+ }
28
+ }
36
+
29
+
37
/* Remove it from the snapshot list */
30
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
38
memmove(s->snapshots + snapshot_index,
31
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
39
s->snapshots + snapshot_index + 1,
32
s->next_child_index == UINT_MAX) {
40
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
33
@@ -XXX,XX +XXX,XX @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
41
index XXXXXXX..XXXXXXX 100755
34
return;
42
--- a/tests/qemu-iotests/080
35
}
43
+++ b/tests/qemu-iotests/080
36
44
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x0
37
+ /* We know now that num_children > threshold, so blkverify must be false */
45
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
38
+ assert(!s->is_blkverify);
46
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
39
+
47
{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
40
bdrv_drained_begin(bs);
48
+{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir
41
49
42
/* We can safely remove this child now */
50
echo
51
echo "== Invalid snapshot L1 table size =="
52
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
53
{ $QEMU_IO -c "open -o overlap-check.inactive-l2=on $TEST_IMG" \
54
-c 'write 0 4k'; } 2>&1 | _filter_qemu_io | _filter_testdir
55
{ $QEMU_IMG snapshot -a test $TEST_IMG; } 2>&1 | _filter_testdir
56
+{ $QEMU_IMG snapshot -d test $TEST_IMG; } 2>&1 | _filter_testdir
57
58
# success, all done
59
echo "*** done"
60
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
61
index XXXXXXX..XXXXXXX 100644
62
--- a/tests/qemu-iotests/080.out
63
+++ b/tests/qemu-iotests/080.out
64
@@ -XXX,XX +XXX,XX @@ Failed to flush the refcount block cache: Invalid argument
65
write failed: Invalid argument
66
qemu-img: Snapshot L1 table offset invalid
67
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invalid argument
68
+qemu-img: Could not delete snapshot 'test': Snapshot L1 table offset invalid
69
70
== Invalid snapshot L1 table size ==
71
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
72
@@ -XXX,XX +XXX,XX @@ Failed to flush the refcount block cache: File too large
73
write failed: File too large
74
qemu-img: Snapshot L1 table too large
75
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File too large
76
+qemu-img: Could not delete snapshot 'test': Snapshot L1 table too large
77
*** done
78
--
43
--
79
2.13.6
44
2.19.1
80
45
81
46
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
2
3
This patch tests that you can add and remove drives from a Quorum
4
using the x-blockdev-change command.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Max Reitz <mreitz@redhat.com>
3
---
8
---
4
tests/qemu-iotests/206 | 436 +++++++++++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/081 | 86 ++++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/206.out | 209 ++++++++++++++++++++++
10
tests/qemu-iotests/081.out | 54 ++++++++++++++++++++++++
6
tests/qemu-iotests/group | 1 +
11
2 files changed, 140 insertions(+)
7
3 files changed, 646 insertions(+)
8
create mode 100755 tests/qemu-iotests/206
9
create mode 100644 tests/qemu-iotests/206.out
10
12
11
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
13
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
12
new file mode 100755
14
index XXXXXXX..XXXXXXX 100755
13
index XXXXXXX..XXXXXXX
15
--- a/tests/qemu-iotests/081
14
--- /dev/null
16
+++ b/tests/qemu-iotests/081
15
+++ b/tests/qemu-iotests/206
17
@@ -XXX,XX +XXX,XX @@ quorum="$quorum,file.children.2.driver=raw"
16
@@ -XXX,XX +XXX,XX @@
18
17
+#!/bin/bash
19
$QEMU_IO -c "open -o $quorum" | _filter_qemu_io
18
+#
20
19
+# Test qcow2 and file image creation
21
+echo
20
+#
22
+echo "== dynamically adding a child to a quorum =="
21
+# Copyright (C) 2018 Red Hat, Inc.
22
+#
23
+# 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
25
+# the Free Software Foundation; either version 2 of the License, or
26
+# (at your option) any later version.
27
+#
28
+# This program is distributed in the hope that it will be useful,
29
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+# GNU General Public License for more details.
32
+#
33
+# 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/>.
35
+#
36
+
23
+
37
+# creator
24
+for verify in false true; do
38
+owner=kwolf@redhat.com
25
+ run_qemu <<EOF
39
+
26
+ { "execute": "qmp_capabilities" }
40
+seq=`basename $0`
27
+ { "execute": "blockdev-add",
41
+echo "QA output created by $seq"
28
+ "arguments": {
42
+
29
+ "driver": "quorum",
43
+here=`pwd`
30
+ "node-name": "drive0-quorum",
44
+status=1    # failure is the default!
31
+ "vote-threshold": 2,
45
+
32
+ "blkverify": ${verify},
46
+# get standard environment, filters and checks
33
+ "children": [
47
+. ./common.rc
34
+ {
48
+. ./common.filter
35
+ "driver": "$IMGFMT",
49
+
36
+ "file": {
50
+_supported_fmt qcow2
37
+ "driver": "file",
51
+_supported_proto file
38
+ "filename": "$TEST_DIR/1.raw"
52
+_supported_os Linux
39
+ }
53
+
40
+ },
54
+function do_run_qemu()
41
+ {
55
+{
42
+ "driver": "$IMGFMT",
56
+ echo Testing: "$@"
43
+ "file": {
57
+ $QEMU -nographic -qmp stdio -serial none "$@"
44
+ "driver": "file",
58
+ echo
45
+ "filename": "$TEST_DIR/2.raw"
59
+}
46
+ }
60
+
47
+ }
61
+function run_qemu()
48
+ ]
62
+{
49
+ }
63
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
50
+ }
64
+ | _filter_qemu | _filter_imgfmt \
51
+ { "execute": "blockdev-add",
65
+ | _filter_actual_image_size
52
+ "arguments": {
66
+}
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
+
67
+
68
+echo
68
+echo
69
+echo "=== Successful image creation (defaults) ==="
69
+echo "== dynamically removing a child from a quorum =="
70
+echo
71
+
70
+
72
+size=$((128 * 1024 * 1024))
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
73
+
106
+
74
+run_qemu <<EOF
107
# success, all done
75
+{ "execute": "qmp_capabilities" }
108
echo "*** done"
76
+{ "execute": "x-blockdev-create",
109
rm -f $seq.full
77
+ "arguments": {
110
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
78
+ "driver": "file",
111
index XXXXXXX..XXXXXXX 100644
79
+ "filename": "$TEST_IMG",
112
--- a/tests/qemu-iotests/081.out
80
+ "size": 0
113
+++ b/tests/qemu-iotests/081.out
81
+ }
114
@@ -XXX,XX +XXX,XX @@ read 10485760/10485760 bytes at offset 0
82
+}
115
83
+{ "execute": "blockdev-add",
116
== checking the blkverify mode with invalid settings ==
84
+ "arguments": {
117
can't open: blkverify=on can only be set if there are exactly two files and vote-threshold is 2
85
+ "driver": "file",
86
+ "node-name": "imgfile",
87
+ "filename": "$TEST_IMG"
88
+ }
89
+}
90
+{ "execute": "x-blockdev-create",
91
+ "arguments": {
92
+ "driver": "$IMGFMT",
93
+ "file": "imgfile",
94
+ "size": $size
95
+ }
96
+}
97
+{ "execute": "quit" }
98
+EOF
99
+
118
+
100
+_img_info --format-specific
119
+== dynamically adding a child to a quorum ==
101
+
102
+echo
103
+echo "=== Successful image creation (inline blockdev-add, explicit defaults) ==="
104
+echo
105
+
106
+# Choose a different size to show that we got a new image
107
+size=$((64 * 1024 * 1024))
108
+
109
+run_qemu <<EOF
110
+{ "execute": "qmp_capabilities" }
111
+{ "execute": "x-blockdev-create",
112
+ "arguments": {
113
+ "driver": "file",
114
+ "filename": "$TEST_IMG",
115
+ "size": 0,
116
+ "preallocation": "off",
117
+ "nocow": false
118
+ }
119
+}
120
+{ "execute": "x-blockdev-create",
121
+ "arguments": {
122
+ "driver": "$IMGFMT",
123
+ "file": {
124
+ "driver": "file",
125
+ "filename": "$TEST_IMG"
126
+ },
127
+ "size": $size,
128
+ "version": "v3",
129
+ "cluster-size": 65536,
130
+ "preallocation": "off",
131
+ "lazy-refcounts": false,
132
+ "refcount-bits": 16
133
+ }
134
+}
135
+{ "execute": "quit" }
136
+EOF
137
+
138
+_img_info --format-specific
139
+
140
+echo
141
+echo "=== Successful image creation (v3 non-default options) ==="
142
+echo
143
+
144
+# Choose a different size to show that we got a new image
145
+size=$((32 * 1024 * 1024))
146
+
147
+run_qemu <<EOF
148
+{ "execute": "qmp_capabilities" }
149
+{ "execute": "x-blockdev-create",
150
+ "arguments": {
151
+ "driver": "file",
152
+ "filename": "$TEST_IMG",
153
+ "size": 0,
154
+ "preallocation": "falloc",
155
+ "nocow": true
156
+ }
157
+}
158
+{ "execute": "x-blockdev-create",
159
+ "arguments": {
160
+ "driver": "$IMGFMT",
161
+ "file": {
162
+ "driver": "file",
163
+ "filename": "$TEST_IMG"
164
+ },
165
+ "size": $size,
166
+ "version": "v3",
167
+ "cluster-size": 2097152,
168
+ "preallocation": "metadata",
169
+ "lazy-refcounts": true,
170
+ "refcount-bits": 1
171
+ }
172
+}
173
+{ "execute": "quit" }
174
+EOF
175
+
176
+_img_info --format-specific
177
+
178
+echo
179
+echo "=== Successful image creation (v2 non-default options) ==="
180
+echo
181
+
182
+mv $TEST_IMG $TEST_IMG.base
183
+
184
+run_qemu <<EOF
185
+{ "execute": "qmp_capabilities" }
186
+{ "execute": "x-blockdev-create",
187
+ "arguments": {
188
+ "driver": "file",
189
+ "filename": "$TEST_IMG",
190
+ "size": 0
191
+ }
192
+}
193
+{ "execute": "x-blockdev-create",
194
+ "arguments": {
195
+ "driver": "$IMGFMT",
196
+ "file": {
197
+ "driver": "file",
198
+ "filename": "$TEST_IMG"
199
+ },
200
+ "size": $size,
201
+ "backing-file": "$TEST_IMG.base",
202
+ "backing-fmt": "qcow2",
203
+ "version": "v2",
204
+ "cluster-size": 512
205
+ }
206
+}
207
+{ "execute": "quit" }
208
+EOF
209
+
210
+_img_info --format-specific
211
+
212
+echo
213
+echo "=== Successful image creation (encrypted) ==="
214
+echo
215
+
216
+run_qemu -object secret,id=keysec0,data="foo" <<EOF
217
+{ "execute": "qmp_capabilities" }
218
+{ "execute": "x-blockdev-create",
219
+ "arguments": {
220
+ "driver": "$IMGFMT",
221
+ "file": {
222
+ "driver": "file",
223
+ "filename": "$TEST_IMG"
224
+ },
225
+ "size": $size,
226
+ "encrypt": {
227
+ "format": "luks",
228
+ "key-secret": "keysec0",
229
+ "cipher-alg": "twofish-128",
230
+ "cipher-mode": "ctr",
231
+ "ivgen-alg": "plain64",
232
+ "ivgen-hash-alg": "md5",
233
+ "hash-alg": "sha1",
234
+ "iter-time": 10
235
+ }
236
+ }
237
+}
238
+{ "execute": "quit" }
239
+EOF
240
+
241
+_img_info --format-specific | _filter_img_info --format-specific
242
+
243
+echo
244
+echo "=== Invalid BlockdevRef ==="
245
+echo
246
+
247
+run_qemu <<EOF
248
+{ "execute": "qmp_capabilities" }
249
+{ "execute": "x-blockdev-create",
250
+ "arguments": {
251
+ "driver": "$IMGFMT",
252
+ "file": "this doesn't exist",
253
+ "size": $size
254
+ }
255
+}
256
+{ "execute": "quit" }
257
+EOF
258
+
259
+
260
+echo
261
+echo "=== Invalid sizes ==="
262
+echo
263
+
264
+# TODO Negative image sizes aren't handled correctly, but this is a problem
265
+# with QAPI's implementation of the 'size' type and affects other commands as
266
+# well. Once this is fixed, we may want to add a test case here.
267
+
268
+# 1. Misaligned image size
269
+# 2. 2^64 - 512
270
+# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
271
+# 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size)
272
+
273
+run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
274
+{ "execute": "qmp_capabilities" }
275
+{ "execute": "x-blockdev-create",
276
+ "arguments": {
277
+ "driver": "$IMGFMT",
278
+ "file": "node0",
279
+ "size": 1234
280
+ }
281
+}
282
+{ "execute": "x-blockdev-create",
283
+ "arguments": {
284
+ "driver": "$IMGFMT",
285
+ "file": "node0",
286
+ "size": 18446744073709551104
287
+ }
288
+}
289
+{ "execute": "x-blockdev-create",
290
+ "arguments": {
291
+ "driver": "$IMGFMT",
292
+ "file": "node0",
293
+ "size": 9223372036854775808
294
+ }
295
+}
296
+{ "execute": "x-blockdev-create",
297
+ "arguments": {
298
+ "driver": "$IMGFMT",
299
+ "file": "node0",
300
+ "size": 9223372036854775296
301
+ }
302
+}
303
+{ "execute": "quit" }
304
+EOF
305
+
306
+echo
307
+echo "=== Invalid version ==="
308
+echo
309
+
310
+run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
311
+{ "execute": "qmp_capabilities" }
312
+{ "execute": "x-blockdev-create",
313
+ "arguments": {
314
+ "driver": "$IMGFMT",
315
+ "file": "node0",
316
+ "size": 67108864,
317
+ "version": "v1"
318
+ }
319
+}
320
+{ "execute": "x-blockdev-create",
321
+ "arguments": {
322
+ "driver": "$IMGFMT",
323
+ "file": "node0",
324
+ "size": 67108864,
325
+ "version": "v2",
326
+ "lazy-refcounts": true
327
+ }
328
+}
329
+{ "execute": "x-blockdev-create",
330
+ "arguments": {
331
+ "driver": "$IMGFMT",
332
+ "file": "node0",
333
+ "size": 67108864,
334
+ "version": "v2",
335
+ "refcount-bits": 8
336
+ }
337
+}
338
+{ "execute": "quit" }
339
+EOF
340
+
341
+echo
342
+echo "=== Invalid backing file options ==="
343
+echo
344
+
345
+run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
346
+{ "execute": "qmp_capabilities" }
347
+{ "execute": "x-blockdev-create",
348
+ "arguments": {
349
+ "driver": "$IMGFMT",
350
+ "file": "node0",
351
+ "size": 67108864,
352
+ "backing-file": "/dev/null",
353
+ "preallocation": "full"
354
+ }
355
+}
356
+{ "execute": "x-blockdev-create",
357
+ "arguments": {
358
+ "driver": "$IMGFMT",
359
+ "file": "node0",
360
+ "size": 67108864,
361
+ "backing-fmt": "$IMGFMT"
362
+ }
363
+}
364
+{ "execute": "quit" }
365
+EOF
366
+
367
+echo
368
+echo "=== Invalid cluster size ==="
369
+echo
370
+
371
+run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
372
+{ "execute": "qmp_capabilities" }
373
+{ "execute": "x-blockdev-create",
374
+ "arguments": {
375
+ "driver": "$IMGFMT",
376
+ "file": "node0",
377
+ "size": 67108864,
378
+ "cluster-size": 1234
379
+ }
380
+}
381
+{ "execute": "x-blockdev-create",
382
+ "arguments": {
383
+ "driver": "$IMGFMT",
384
+ "file": "node0",
385
+ "size": 67108864,
386
+ "cluster-size": 128
387
+ }
388
+}
389
+{ "execute": "x-blockdev-create",
390
+ "arguments": {
391
+ "driver": "$IMGFMT",
392
+ "file": "node0",
393
+ "size": 67108864,
394
+ "cluster-size": 4194304
395
+ }
396
+}
397
+{ "execute": "x-blockdev-create",
398
+ "arguments": {
399
+ "driver": "$IMGFMT",
400
+ "file": "node0",
401
+ "size": 67108864,
402
+ "cluster-size": 0
403
+ }
404
+}
405
+{ "execute": "x-blockdev-create",
406
+ "arguments": {
407
+ "driver": "$IMGFMT",
408
+ "file": "node0",
409
+ "size": 281474976710656,
410
+ "cluster-size": 512
411
+ }
412
+}
413
+{ "execute": "quit" }
414
+EOF
415
+
416
+echo
417
+echo "=== Invalid refcount width ==="
418
+echo
419
+
420
+run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
421
+{ "execute": "qmp_capabilities" }
422
+{ "execute": "x-blockdev-create",
423
+ "arguments": {
424
+ "driver": "$IMGFMT",
425
+ "file": "node0",
426
+ "size": 67108864,
427
+ "refcount-bits": 128
428
+ }
429
+}
430
+{ "execute": "x-blockdev-create",
431
+ "arguments": {
432
+ "driver": "$IMGFMT",
433
+ "file": "node0",
434
+ "size": 67108864,
435
+ "refcount-bits": 0
436
+ }
437
+}
438
+{ "execute": "x-blockdev-create",
439
+ "arguments": {
440
+ "driver": "$IMGFMT",
441
+ "file": "node0",
442
+ "size": 67108864,
443
+ "refcount-bits": 7
444
+ }
445
+}
446
+{ "execute": "quit" }
447
+EOF
448
+
449
+# success, all done
450
+echo "*** done"
451
+rm -f $seq.full
452
+status=0
453
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
454
new file mode 100644
455
index XXXXXXX..XXXXXXX
456
--- /dev/null
457
+++ b/tests/qemu-iotests/206.out
458
@@ -XXX,XX +XXX,XX @@
459
+QA output created by 206
460
+
461
+=== Successful image creation (defaults) ===
462
+
463
+Testing:
120
+Testing:
464
+QMP_VERSION
121
+QMP_VERSION
465
+{"return": {}}
122
+{"return": {}}
466
+{"return": {}}
123
+{"return": {}}
467
+{"return": {}}
124
+{"return": {}}
468
+{"return": {}}
125
+{"return": {}}
469
+{"return": {}}
126
+{"return": {}}
470
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
127
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
471
+
128
+
472
+image: TEST_DIR/t.IMGFMT
129
+Testing:
473
+file format: IMGFMT
130
+QMP_VERSION
474
+virtual size: 128M (134217728 bytes)
131
+{"return": {}}
475
+cluster_size: 65536
132
+{"return": {}}
476
+Format specific information:
133
+{"return": {}}
477
+ compat: 1.1
134
+{"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}}
478
+ lazy refcounts: false
135
+{"return": {}}
479
+ refcount bits: 16
136
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
480
+ corrupt: false
481
+
137
+
482
+=== Successful image creation (inline blockdev-add, explicit defaults) ===
483
+
138
+
139
+== dynamically removing a child from a quorum ==
484
+Testing:
140
+Testing:
485
+QMP_VERSION
141
+QMP_VERSION
486
+{"return": {}}
142
+{"return": {}}
487
+{"return": {}}
143
+{"return": {}}
488
+{"return": {}}
144
+{"return": {}}
489
+{"return": {}}
145
+{"return": {}}
490
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
146
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
491
+
147
+
492
+image: TEST_DIR/t.IMGFMT
148
+Testing:
493
+file format: IMGFMT
149
+QMP_VERSION
494
+virtual size: 64M (67108864 bytes)
150
+{"return": {}}
495
+cluster_size: 65536
151
+{"return": {}}
496
+Format specific information:
152
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
497
+ compat: 1.1
153
+{"return": {}}
498
+ lazy refcounts: false
154
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
499
+ refcount bits: 16
500
+ corrupt: false
501
+
155
+
502
+=== Successful image creation (v3 non-default options) ===
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}}
503
+
163
+
504
+Testing:
164
+Testing:
505
+QMP_VERSION
165
+QMP_VERSION
506
+{"return": {}}
166
+{"return": {}}
507
+{"return": {}}
167
+{"return": {}}
508
+{"return": {}}
168
+{"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}}
509
+{"return": {}}
169
+{"return": {}}
510
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
170
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
511
+
171
+
512
+image: TEST_DIR/t.IMGFMT
172
*** done
513
+file format: IMGFMT
514
+virtual size: 32M (33554432 bytes)
515
+cluster_size: 2097152
516
+Format specific information:
517
+ compat: 1.1
518
+ lazy refcounts: true
519
+ refcount bits: 1
520
+ corrupt: false
521
+
522
+=== Successful image creation (v2 non-default options) ===
523
+
524
+Testing:
525
+QMP_VERSION
526
+{"return": {}}
527
+{"return": {}}
528
+{"return": {}}
529
+{"return": {}}
530
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
531
+
532
+image: TEST_DIR/t.IMGFMT
533
+file format: IMGFMT
534
+virtual size: 32M (33554432 bytes)
535
+cluster_size: 512
536
+backing file: TEST_DIR/t.IMGFMT.base
537
+backing file format: IMGFMT
538
+Format specific information:
539
+ compat: 0.10
540
+ refcount bits: 16
541
+
542
+=== Successful image creation (encrypted) ===
543
+
544
+Testing: -object secret,id=keysec0,data=foo
545
+QMP_VERSION
546
+{"return": {}}
547
+{"return": {}}
548
+{"return": {}}
549
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
550
+
551
+image: TEST_DIR/t.IMGFMT
552
+file format: IMGFMT
553
+virtual size: 32M (33554432 bytes)
554
+Format specific information:
555
+ compat: 1.1
556
+ lazy refcounts: false
557
+ refcount bits: 16
558
+ encrypt:
559
+ ivgen alg: plain64
560
+ hash alg: sha1
561
+ cipher alg: twofish-128
562
+ uuid: 00000000-0000-0000-0000-000000000000
563
+ format: luks
564
+ cipher mode: ctr
565
+ slots:
566
+ [0]:
567
+ active: true
568
+ iters: 1024
569
+ key offset: 4096
570
+ stripes: 4000
571
+ [1]:
572
+ active: false
573
+ key offset: 69632
574
+ [2]:
575
+ active: false
576
+ key offset: 135168
577
+ [3]:
578
+ active: false
579
+ key offset: 200704
580
+ [4]:
581
+ active: false
582
+ key offset: 266240
583
+ [5]:
584
+ active: false
585
+ key offset: 331776
586
+ [6]:
587
+ active: false
588
+ key offset: 397312
589
+ [7]:
590
+ active: false
591
+ key offset: 462848
592
+ payload offset: 528384
593
+ master key iters: 1024
594
+ corrupt: false
595
+
596
+=== Invalid BlockdevRef ===
597
+
598
+Testing:
599
+QMP_VERSION
600
+{"return": {}}
601
+{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
602
+{"return": {}}
603
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
604
+
605
+
606
+=== Invalid sizes ===
607
+
608
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
609
+QMP_VERSION
610
+{"return": {}}
611
+{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}}
612
+{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}}
613
+{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}}
614
+{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}}
615
+{"return": {}}
616
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
617
+
618
+
619
+=== Invalid version ===
620
+
621
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
622
+QMP_VERSION
623
+{"return": {}}
624
+{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
625
+{"error": {"class": "GenericError", "desc": "Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)"}}
626
+{"error": {"class": "GenericError", "desc": "Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)"}}
627
+{"return": {}}
628
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
629
+
630
+
631
+=== Invalid backing file options ===
632
+
633
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
634
+QMP_VERSION
635
+{"return": {}}
636
+{"error": {"class": "GenericError", "desc": "Backing file and preallocation cannot be used at the same time"}}
637
+{"error": {"class": "GenericError", "desc": "Backing format cannot be used without backing file"}}
638
+{"return": {}}
639
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
640
+
641
+
642
+=== Invalid cluster size ===
643
+
644
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
645
+QMP_VERSION
646
+{"return": {}}
647
+{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
648
+{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
649
+{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
650
+{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
651
+{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}}
652
+{"return": {}}
653
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
654
+
655
+
656
+=== Invalid refcount width ===
657
+
658
+Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
659
+QMP_VERSION
660
+{"return": {}}
661
+{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
662
+{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
663
+{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
664
+{"return": {}}
665
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
666
+
667
+*** done
668
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
669
index XXXXXXX..XXXXXXX 100644
670
--- a/tests/qemu-iotests/group
671
+++ b/tests/qemu-iotests/group
672
@@ -XXX,XX +XXX,XX @@
673
203 rw auto
674
204 rw auto quick
675
205 rw auto quick
676
+206 rw auto
677
--
173
--
678
2.13.6
174
2.19.1
679
175
680
176
diff view generated by jsdifflib
1
Instead of passing a separate BlockDriverState* into qcow2_co_create(),
1
To fully change the read-only state of a node, we must not only change
2
make use of the BlockdevRef that is included in BlockdevCreateOptions.
2
bs->read_only, but also update bs->open_flags.
3
3
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
---
7
---
8
include/block/block.h | 1 +
8
block.c | 7 +++++++
9
block.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
9
1 file changed, 7 insertions(+)
10
block/qcow2.c | 39 +++++++++++++++++++++++++--------------
11
3 files changed, 73 insertions(+), 14 deletions(-)
12
10
13
diff --git a/include/block/block.h b/include/block/block.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block.h
16
+++ b/include/block/block.h
17
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
18
BlockDriverState* parent,
19
const BdrvChildRole *child_role,
20
bool allow_none, Error **errp);
21
+BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
22
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
23
Error **errp);
24
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
25
diff --git a/block.c b/block.c
11
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
13
--- a/block.c
28
+++ b/block.c
14
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
30
#include "qapi/qmp/qdict.h"
16
}
31
#include "qapi/qmp/qjson.h"
17
32
#include "qapi/qmp/qstring.h"
18
bs->read_only = read_only;
33
+#include "qapi/qobject-output-visitor.h"
34
+#include "qapi/qapi-visit-block-core.h"
35
#include "sysemu/block-backend.h"
36
#include "sysemu/sysemu.h"
37
#include "qemu/notify.h"
38
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
39
return c;
40
}
41
42
+/* TODO Future callers may need to specify parent/child_role in order for
43
+ * option inheritance to work. Existing callers use it for the root node. */
44
+BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
45
+{
46
+ BlockDriverState *bs = NULL;
47
+ Error *local_err = NULL;
48
+ QObject *obj = NULL;
49
+ QDict *qdict = NULL;
50
+ const char *reference = NULL;
51
+ Visitor *v = NULL;
52
+
19
+
53
+ if (ref->type == QTYPE_QSTRING) {
20
+ if (read_only) {
54
+ reference = ref->u.reference;
21
+ bs->open_flags &= ~BDRV_O_RDWR;
55
+ } else {
22
+ } else {
56
+ BlockdevOptions *options = &ref->u.definition;
23
+ bs->open_flags |= BDRV_O_RDWR;
57
+ assert(ref->type == QTYPE_QDICT);
58
+
59
+ v = qobject_output_visitor_new(&obj);
60
+ visit_type_BlockdevOptions(v, NULL, &options, &local_err);
61
+ if (local_err) {
62
+ error_propagate(errp, local_err);
63
+ goto fail;
64
+ }
65
+ visit_complete(v, &obj);
66
+
67
+ qdict = qobject_to_qdict(obj);
68
+ qdict_flatten(qdict);
69
+
70
+ /* bdrv_open_inherit() defaults to the values in bdrv_flags (for
71
+ * compatibility with other callers) rather than what we want as the
72
+ * real defaults. Apply the defaults here instead. */
73
+ qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
74
+ qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
75
+ qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
76
+ }
24
+ }
77
+
25
+
78
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
26
return 0;
79
+ obj = NULL;
80
+
81
+fail:
82
+ qobject_decref(obj);
83
+ visit_free(v);
84
+ return bs;
85
+}
86
+
87
static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
88
int flags,
89
QDict *snapshot_options,
90
diff --git a/block/qcow2.c b/block/qcow2.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/block/qcow2.c
93
+++ b/block/qcow2.c
94
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
95
}
27
}
96
28
97
static int coroutine_fn
98
-qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
99
- QemuOpts *opts, const char *encryptfmt, Error **errp)
100
+qcow2_co_create(BlockdevCreateOptions *create_options, QemuOpts *opts,
101
+ const char *encryptfmt, Error **errp)
102
{
103
BlockdevCreateOptionsQcow2 *qcow2_opts;
104
QDict *options;
105
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
106
* 2 GB for 64k clusters, and we don't want to have a 2 GB initial file
107
* size for any qcow2 image.
108
*/
109
- BlockBackend *blk;
110
+ BlockBackend *blk = NULL;
111
+ BlockDriverState *bs = NULL;
112
QCowHeader *header;
113
size_t cluster_size;
114
int version;
115
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
116
Error *local_err = NULL;
117
int ret;
118
119
- /* Validate options and set default values */
120
assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2);
121
qcow2_opts = &create_options->u.qcow2;
122
123
+ bs = bdrv_open_blockdev_ref(qcow2_opts->file, errp);
124
+ if (bs == NULL) {
125
+ return -EIO;
126
+ }
127
+
128
+ /* Validate options and set default values */
129
if (!QEMU_IS_ALIGNED(qcow2_opts->size, BDRV_SECTOR_SIZE)) {
130
error_setg(errp, "Image size must be a multiple of 512 bytes");
131
ret = -EINVAL;
132
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
133
}
134
135
if (!validate_cluster_size(cluster_size, errp)) {
136
- return -EINVAL;
137
+ ret = -EINVAL;
138
+ goto out;
139
}
140
141
if (!qcow2_opts->has_preallocation) {
142
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
143
{
144
error_setg(errp, "Backing file and preallocation cannot be used at "
145
"the same time");
146
- return -EINVAL;
147
+ ret = -EINVAL;
148
+ goto out;
149
}
150
if (qcow2_opts->has_backing_fmt && !qcow2_opts->has_backing_file) {
151
error_setg(errp, "Backing format cannot be used without backing file");
152
- return -EINVAL;
153
+ ret = -EINVAL;
154
+ goto out;
155
}
156
157
if (!qcow2_opts->has_lazy_refcounts) {
158
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
159
if (version < 3 && qcow2_opts->lazy_refcounts) {
160
error_setg(errp, "Lazy refcounts only supported with compatibility "
161
"level 1.1 and above (use compat=1.1 or greater)");
162
- return -EINVAL;
163
+ ret = -EINVAL;
164
+ goto out;
165
}
166
167
if (!qcow2_opts->has_refcount_bits) {
168
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
169
{
170
error_setg(errp, "Refcount width must be a power of two and may not "
171
"exceed 64 bits");
172
- return -EINVAL;
173
+ ret = -EINVAL;
174
+ goto out;
175
}
176
if (version < 3 && qcow2_opts->refcount_bits != 16) {
177
error_setg(errp, "Different refcount widths than 16 bits require "
178
"compatibility level 1.1 or above (use compat=1.1 or "
179
"greater)");
180
- return -EINVAL;
181
+ ret = -EINVAL;
182
+ goto out;
183
}
184
refcount_order = ctz32(qcow2_opts->refcount_bits);
185
186
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockDriverState *bs, BlockdevCreateOptions *create_options,
187
188
ret = 0;
189
out:
190
- if (blk) {
191
- blk_unref(blk);
192
- }
193
+ blk_unref(blk);
194
+ bdrv_unref(bs);
195
return ret;
196
}
197
198
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
199
.refcount_bits = refcount_bits,
200
},
201
};
202
- ret = qcow2_co_create(bs, &create_options, opts, encryptfmt, errp);
203
+ ret = qcow2_co_create(&create_options, opts, encryptfmt, errp);
204
if (ret < 0) {
205
goto finish;
206
}
207
--
29
--
208
2.13.6
30
2.19.1
209
31
210
32
diff view generated by jsdifflib
1
This makes the host-key-check option available in blockdev-add.
1
If a management application builds the block graph node by node, the
2
protocol layer doesn't inherit its read-only option from the format
3
layer any more, so it must be set explicitly.
4
5
Backing files should work on read-only storage, but at the same time, a
6
block job like commit should be able to reopen them read-write if they
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
13
A simple workaround for the problem in the management tool would be to
14
open the protocol layer always read-write and to make only the format
15
layer read-only for backing files. However, sometimes the file is
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
22
The documentation for this option is consciously phrased in a way that
23
allows QEMU to switch to a better model eventually: Instead of trying
24
when the image is first opened, making the read-only flag dynamic and
25
changing it automatically whenever the first BLK_PERM_WRITE user is
26
attached or the last one is detached would be much more useful
27
behaviour.
28
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.
2
37
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
5
---
40
---
6
qapi/block-core.json | 63 +++++++++++++++++++++++++++++++++++--
41
qapi/block-core.json | 7 +++++++
7
block/ssh.c | 88 +++++++++++++++++++++++++++++++++-------------------
42
include/block/block.h | 2 ++
8
2 files changed, 117 insertions(+), 34 deletions(-)
43
block.c | 17 +++++++++++++++++
44
block/vvfat.c | 1 +
45
blockdev.c | 2 +-
46
5 files changed, 28 insertions(+), 1 deletion(-)
9
47
10
diff --git a/qapi/block-core.json b/qapi/block-core.json
48
diff --git a/qapi/block-core.json b/qapi/block-core.json
11
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
12
--- a/qapi/block-core.json
50
--- a/qapi/block-core.json
13
+++ b/qapi/block-core.json
51
+++ b/qapi/block-core.json
14
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
15
'*encrypt': 'BlockdevQcow2Encryption' } }
53
# either generally or in certain configurations. In this case,
16
54
# the default value does not work and the option must be
17
##
55
# specified explicitly.
18
+# @SshHostKeyCheckMode:
56
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
19
+#
57
+# decide not to open the image read-write as requested, but
20
+# @none Don't check the host key at all
58
+# fall back to read-only instead (and switch between the modes
21
+# @hash Compare the host key with a given hash
59
+# later), e.g. depending on whether the image file is writable
22
+# @known_hosts Check the host key against the known_hosts file
60
+# or whether a writing user is attached to the node
23
+#
61
+# (default: false, since 3.1)
24
+# Since: 2.12
62
# @detect-zeroes: detect and optimize zero writes (Since 2.1)
25
+##
63
# (default: off)
26
+{ 'enum': 'SshHostKeyCheckMode',
64
# @force-share: force share all permission on added nodes.
27
+ 'data': [ 'none', 'hash', 'known_hosts' ] }
28
+
29
+##
30
+# @SshHostKeyCheckHashType:
31
+#
32
+# @md5 The given hash is an md5 hash
33
+# @sha1 The given hash is an sha1 hash
34
+#
35
+# Since: 2.12
36
+##
37
+{ 'enum': 'SshHostKeyCheckHashType',
38
+ 'data': [ 'md5', 'sha1' ] }
39
+
40
+##
41
+# @SshHostKeyHash:
42
+#
43
+# @type The hash algorithm used for the hash
44
+# @hash The expected hash value
45
+#
46
+# Since: 2.12
47
+##
48
+{ 'struct': 'SshHostKeyHash',
49
+ 'data': { 'type': 'SshHostKeyCheckHashType',
50
+ 'hash': 'str' }}
51
+
52
+##
53
+# @SshHostKeyDummy:
54
+#
55
+# For those union branches that don't need additional fields.
56
+#
57
+# Since: 2.12
58
+##
59
+{ 'struct': 'SshHostKeyDummy',
60
+ 'data': {} }
61
+
62
+##
63
+# @SshHostKeyCheck:
64
+#
65
+# Since: 2.12
66
+##
67
+{ 'union': 'SshHostKeyCheck',
68
+ 'base': { 'mode': 'SshHostKeyCheckMode' },
69
+ 'discriminator': 'mode',
70
+ 'data': { 'none': 'SshHostKeyDummy',
71
+ 'hash': 'SshHostKeyHash',
72
+ 'known_hosts': 'SshHostKeyDummy' } }
73
+
74
+##
75
# @BlockdevOptionsSsh:
76
#
77
# @server: host address
78
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@
79
# @user: user as which to connect, defaults to current
66
'*discard': 'BlockdevDiscardOptions',
80
# local user name
67
'*cache': 'BlockdevCacheOptions',
81
#
68
'*read-only': 'bool',
82
-# TODO: Expose the host_key_check option in QMP
69
+ '*auto-read-only': 'bool',
83
+# @host-key-check: Defines how and what to check the host key against
70
'*force-share': 'bool',
84
+# (default: known_hosts)
71
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
85
#
72
'discriminator': 'driver',
86
# Since: 2.9
73
diff --git a/include/block/block.h b/include/block/block.h
87
##
88
{ 'struct': 'BlockdevOptionsSsh',
89
'data': { 'server': 'InetSocketAddress',
90
'path': 'str',
91
- '*user': 'str' } }
92
+ '*user': 'str',
93
+ '*host-key-check': 'SshHostKeyCheck' } }
94
95
96
##
97
diff --git a/block/ssh.c b/block/ssh.c
98
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
99
--- a/block/ssh.c
75
--- a/include/block/block.h
100
+++ b/block/ssh.c
76
+++ b/include/block/block.h
101
@@ -XXX,XX +XXX,XX @@ check_host_key_hash(BDRVSSHState *s, const char *hash,
77
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
78
select an appropriate protocol driver,
79
ignoring the format layer */
80
#define BDRV_O_NO_IO 0x10000 /* don't initialize for I/O */
81
+#define BDRV_O_AUTO_RDONLY 0x20000 /* degrade to read-only if opening read-write fails */
82
83
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
84
85
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
86
#define BDRV_OPT_CACHE_DIRECT "cache.direct"
87
#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
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
94
index XXXXXXX..XXXXXXX 100644
95
--- a/block.c
96
+++ b/block.c
97
@@ -XXX,XX +XXX,XX @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
98
99
/* Inherit the read-only option from the parent if it's not set */
100
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
101
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
102
103
/* Our block drivers take care to send flushes and respect unmap policy,
104
* so we can default to enable both on lower layers regardless of the
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
106
107
/* backing files always opened read-only */
108
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
109
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
110
flags &= ~BDRV_O_COPY_ON_READ;
111
112
/* snapshot=on is handled on the top layer */
113
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
114
*flags |= BDRV_O_RDWR;
115
}
116
117
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
118
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
119
+ *flags |= BDRV_O_AUTO_RDONLY;
120
+ }
102
}
121
}
103
122
104
static int check_host_key(BDRVSSHState *s, const char *host, int port,
123
static void update_options_from_flags(QDict *options, int flags)
105
- const char *host_key_check, Error **errp)
124
@@ -XXX,XX +XXX,XX @@ static void update_options_from_flags(QDict *options, int flags)
106
+ SshHostKeyCheck *hkc, Error **errp)
125
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
107
{
126
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
108
- /* host_key_check=no */
109
- if (strcmp(host_key_check, "no") == 0) {
110
- return 0;
111
- }
112
+ SshHostKeyCheckMode mode;
113
114
- /* host_key_check=md5:xx:yy:zz:... */
115
- if (strncmp(host_key_check, "md5:", 4) == 0) {
116
- return check_host_key_hash(s, &host_key_check[4],
117
- LIBSSH2_HOSTKEY_HASH_MD5, 16, errp);
118
- }
119
-
120
- /* host_key_check=sha1:xx:yy:zz:... */
121
- if (strncmp(host_key_check, "sha1:", 5) == 0) {
122
- return check_host_key_hash(s, &host_key_check[5],
123
- LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp);
124
+ if (hkc) {
125
+ mode = hkc->mode;
126
+ } else {
127
+ mode = SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS;
128
}
127
}
129
128
+ if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
130
- /* host_key_check=yes */
129
+ qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
131
- if (strcmp(host_key_check, "yes") == 0) {
130
+ flags & BDRV_O_AUTO_RDONLY);
132
+ switch (mode) {
131
+ }
133
+ case SSH_HOST_KEY_CHECK_MODE_NONE:
134
+ return 0;
135
+ case SSH_HOST_KEY_CHECK_MODE_HASH:
136
+ if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_MD5) {
137
+ return check_host_key_hash(s, hkc->u.hash.hash,
138
+ LIBSSH2_HOSTKEY_HASH_MD5, 16, errp);
139
+ } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA1) {
140
+ return check_host_key_hash(s, hkc->u.hash.hash,
141
+ LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp);
142
+ }
143
+ g_assert_not_reached();
144
+ break;
145
+ case SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS:
146
return check_host_key_knownhosts(s, host, port, errp);
147
+ default:
148
+ g_assert_not_reached();
149
}
150
151
- error_setg(errp, "unknown host_key_check setting (%s)", host_key_check);
152
return -EINVAL;
153
}
132
}
154
133
155
@@ -XXX,XX +XXX,XX @@ static QemuOptsList ssh_runtime_opts = {
134
static void bdrv_assign_node_name(BlockDriverState *bs,
156
.type = QEMU_OPT_NUMBER,
135
@@ -XXX,XX +XXX,XX @@ QemuOptsList bdrv_runtime_opts = {
157
.help = "Port to connect to",
136
.type = QEMU_OPT_BOOL,
137
.help = "Node is opened in read-only mode",
158
},
138
},
159
+ {
139
+ {
160
+ .name = "host_key_check",
140
+ .name = BDRV_OPT_AUTO_READ_ONLY,
161
+ .type = QEMU_OPT_STRING,
141
+ .type = QEMU_OPT_BOOL,
162
+ .help = "Defines how and what to check the host key against",
142
+ .help = "Node can become read-only if opening read-write fails",
163
+ },
143
+ },
164
{ /* end of list */ }
144
{
165
},
145
.name = "detect-zeroes",
166
};
146
.type = QEMU_OPT_STRING,
167
147
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
168
-static bool ssh_process_legacy_socket_options(QDict *output_opts,
148
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
169
- QemuOpts *legacy_opts,
149
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
170
- Error **errp)
150
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
171
+static bool ssh_process_legacy_options(QDict *output_opts,
151
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
172
+ QemuOpts *legacy_opts,
152
+
173
+ Error **errp)
153
}
154
155
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
156
diff --git a/block/vvfat.c b/block/vvfat.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/vvfat.c
159
+++ b/block/vvfat.c
160
@@ -XXX,XX +XXX,XX @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
161
int parent_flags, QDict *parent_options)
174
{
162
{
175
const char *host = qemu_opt_get(legacy_opts, "host");
163
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
176
const char *port = qemu_opt_get(legacy_opts, "port");
164
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
177
+ const char *host_key_check = qemu_opt_get(legacy_opts, "host_key_check");
165
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
178
179
if (!host && port) {
180
error_setg(errp, "port may not be used without host");
181
@@ -XXX,XX +XXX,XX @@ static bool ssh_process_legacy_socket_options(QDict *output_opts,
182
qdict_put_str(output_opts, "server.port", port ?: stringify(22));
183
}
184
185
+ if (host_key_check) {
186
+ if (strcmp(host_key_check, "no") == 0) {
187
+ qdict_put_str(output_opts, "host-key-check.mode", "none");
188
+ } else if (strncmp(host_key_check, "md5:", 4) == 0) {
189
+ qdict_put_str(output_opts, "host-key-check.mode", "hash");
190
+ qdict_put_str(output_opts, "host-key-check.type", "md5");
191
+ qdict_put_str(output_opts, "host-key-check.hash",
192
+ &host_key_check[4]);
193
+ } else if (strncmp(host_key_check, "sha1:", 5) == 0) {
194
+ qdict_put_str(output_opts, "host-key-check.mode", "hash");
195
+ qdict_put_str(output_opts, "host-key-check.type", "sha1");
196
+ qdict_put_str(output_opts, "host-key-check.hash",
197
+ &host_key_check[5]);
198
+ } else if (strcmp(host_key_check, "yes") == 0) {
199
+ qdict_put_str(output_opts, "host-key-check.mode", "known_hosts");
200
+ } else {
201
+ error_setg(errp, "unknown host_key_check setting (%s)",
202
+ host_key_check);
203
+ return false;
204
+ }
205
+ }
206
+
207
return true;
208
}
166
}
209
167
210
@@ -XXX,XX +XXX,XX @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp)
168
diff --git a/blockdev.c b/blockdev.c
211
goto fail;
169
index XXXXXXX..XXXXXXX 100644
212
}
170
--- a/blockdev.c
213
171
+++ b/blockdev.c
214
- if (!ssh_process_legacy_socket_options(options, opts, errp)) {
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
215
+ if (!ssh_process_legacy_options(options, opts, errp)) {
173
216
goto fail;
174
bdrv_flags = blk_get_open_flags_from_root_state(blk);
217
}
175
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
218
176
- BDRV_O_PROTOCOL);
219
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
177
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
220
{
178
221
BlockdevOptionsSsh *opts;
179
if (!has_read_only) {
222
int r, ret;
180
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
223
- const char *user, *host_key_check;
224
+ const char *user;
225
long port = 0;
226
227
- host_key_check = qdict_get_try_str(options, "host_key_check");
228
- if (!host_key_check) {
229
- host_key_check = "yes";
230
- } else {
231
- qdict_del(options, "host_key_check");
232
- }
233
-
234
opts = ssh_parse_options(options, errp);
235
if (opts == NULL) {
236
return -EINVAL;
237
@@ -XXX,XX +XXX,XX @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
238
}
239
240
/* Check the remote host's key against known_hosts. */
241
- ret = check_host_key(s, s->inet->host, port, host_key_check,
242
- errp);
243
+ ret = check_host_key(s, s->inet->host, port, opts->host_key_check, errp);
244
if (ret < 0) {
245
goto err;
246
}
247
--
181
--
248
2.13.6
182
2.19.1
249
183
250
184
diff view generated by jsdifflib
1
This is almost exactly the same code. The differences are that
1
Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
2
qemu_rbd_connect() supports BlockdevOptionsRbd.server and that the cache
2
calling rbd_open(), but neglected to close the image again in this error
3
mode is set explicitly.
3
path. The error path should contain everything that the regular close
4
function qemu_rbd_close() contains.
4
5
5
Supporting 'server' is a welcome new feature for image creation.
6
This adds the missing rbd_close() call.
6
Caching is disabled by default, so leave it that way.
7
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
---
10
---
11
block/rbd.c | 54 ++++++++++--------------------------------------------
11
block/rbd.c | 1 +
12
1 file changed, 10 insertions(+), 44 deletions(-)
12
1 file changed, 1 insertion(+)
13
13
14
diff --git a/block/rbd.c b/block/rbd.c
14
diff --git a/block/rbd.c b/block/rbd.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/rbd.c
16
--- a/block/rbd.c
17
+++ b/block/rbd.c
17
+++ b/block/rbd.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
18
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
19
char *snap;
19
"automatically marking the image read-only.");
20
} BDRVRBDState;
20
r = bdrv_set_read_only(bs, true, &local_err);
21
21
if (r < 0) {
22
+static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
22
+ rbd_close(s->image);
23
+ BlockdevOptionsRbd *opts, bool cache,
23
error_propagate(errp, local_err);
24
+ const char *keypairs, const char *secretid,
24
goto failed_open;
25
+ Error **errp);
25
}
26
+
27
static char *qemu_rbd_next_tok(char *src, char delim, char **p)
28
{
29
char *end;
30
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_do_create(BlockdevCreateOptions *options,
31
return -EINVAL;
32
}
33
34
- /* TODO Remove the limitation */
35
- if (opts->location->has_server) {
36
- error_setg(errp, "Can't specify server for image creation");
37
- return -EINVAL;
38
- }
39
-
40
if (opts->has_cluster_size) {
41
int64_t objsize = opts->cluster_size;
42
if ((objsize - 1) & objsize) { /* not a power of 2? */
43
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_do_create(BlockdevCreateOptions *options,
44
obj_order = ctz32(objsize);
45
}
46
47
- ret = rados_create(&cluster, opts->location->user);
48
+ ret = qemu_rbd_connect(&cluster, &io_ctx, opts->location, false, keypairs,
49
+ password_secret, errp);
50
if (ret < 0) {
51
- error_setg_errno(errp, -ret, "error initializing");
52
return ret;
53
}
54
55
- /* try default location when conf=NULL, but ignore failure */
56
- ret = rados_conf_read_file(cluster, opts->location->conf);
57
- if (opts->location->conf && ret < 0) {
58
- error_setg_errno(errp, -ret, "error reading conf file %s",
59
- opts->location->conf);
60
- ret = -EIO;
61
- goto shutdown;
62
- }
63
-
64
- ret = qemu_rbd_set_keypairs(cluster, keypairs, errp);
65
- if (ret < 0) {
66
- ret = -EIO;
67
- goto shutdown;
68
- }
69
-
70
- if (qemu_rbd_set_auth(cluster, password_secret, errp) < 0) {
71
- ret = -EIO;
72
- goto shutdown;
73
- }
74
-
75
- ret = rados_connect(cluster);
76
- if (ret < 0) {
77
- error_setg_errno(errp, -ret, "error connecting");
78
- goto shutdown;
79
- }
80
-
81
- ret = rados_ioctx_create(cluster, opts->location->pool, &io_ctx);
82
- if (ret < 0) {
83
- error_setg_errno(errp, -ret, "error opening pool %s",
84
- opts->location->pool);
85
- goto shutdown;
86
- }
87
-
88
ret = rbd_create(io_ctx, opts->location->image, opts->size, &obj_order);
89
if (ret < 0) {
90
error_setg_errno(errp, -ret, "error rbd create");
91
+ goto out;
92
}
93
94
- rados_ioctx_destroy(io_ctx);
95
-
96
ret = 0;
97
-shutdown:
98
+out:
99
+ rados_ioctx_destroy(io_ctx);
100
rados_shutdown(cluster);
101
return ret;
102
}
103
--
26
--
104
2.13.6
27
2.19.1
105
28
106
29
diff view generated by jsdifflib
1
We'll use a separate source file for image creation, and we need to
1
Some block drivers have traditionally changed their node to read-only
2
check there whether the requested driver is whitelisted.
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
5
Now that we have auto-read-only=on, enable these drivers to make use of
6
the option.
7
8
This is the only use of bdrv_set_read_only(), so we can make it a bit
9
more specific and turn it into a bdrv_apply_auto_read_only() that is
10
more convenient for drivers to use.
3
11
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
14
---
8
include/block/block.h | 1 +
15
include/block/block.h | 3 ++-
9
block.c | 2 +-
16
block.c | 42 +++++++++++++++++++++++++++---------------
10
2 files changed, 2 insertions(+), 1 deletion(-)
17
block/bochs.c | 17 ++++++-----------
18
block/cloop.c | 16 +++++-----------
19
block/dmg.c | 16 +++++-----------
20
block/rbd.c | 15 ++++-----------
21
block/vvfat.c | 10 ++--------
22
7 files changed, 51 insertions(+), 68 deletions(-)
11
23
12
diff --git a/include/block/block.h b/include/block/block.h
24
diff --git a/include/block/block.h b/include/block/block.h
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/include/block/block.h
26
--- a/include/block/block.h
15
+++ b/include/block/block.h
27
+++ b/include/block/block.h
16
@@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm);
28
@@ -XXX,XX +XXX,XX @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
17
void bdrv_init(void);
29
bool bdrv_is_read_only(BlockDriverState *bs);
18
void bdrv_init_with_whitelist(void);
30
int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
19
bool bdrv_uses_whitelist(void);
31
bool ignore_allow_rdw, Error **errp);
20
+int bdrv_is_whitelisted(BlockDriver *drv, bool read_only);
32
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
21
BlockDriver *bdrv_find_protocol(const char *filename,
33
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
22
bool allow_protocol_prefix,
34
+ Error **errp);
23
Error **errp);
35
bool bdrv_is_writable(BlockDriverState *bs);
36
bool bdrv_is_sg(BlockDriverState *bs);
37
bool bdrv_is_inserted(BlockDriverState *bs);
24
diff --git a/block.c b/block.c
38
diff --git a/block.c b/block.c
25
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
26
--- a/block.c
40
--- a/block.c
27
+++ b/block.c
41
+++ b/block.c
28
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_find_format(const char *format_name)
42
@@ -XXX,XX +XXX,XX @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
29
return bdrv_do_find_format(format_name);
43
return 0;
30
}
44
}
31
45
32
-static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
46
-/* TODO Remove (deprecated since 2.11)
33
+int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
47
- * Block drivers are not supposed to automatically change bs->read_only.
48
- * Instead, they should just check whether they can provide what the user
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)
34
{
64
{
35
static const char *whitelist_rw[] = {
65
int ret = 0;
36
CONFIG_BDRV_RW_WHITELIST
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
+
91
return 0;
92
+
93
+fail:
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
+ }
112
+
113
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
114
false, 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
+ }
145
+
146
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
147
false, 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
+ }
178
+
179
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
180
false, errp);
181
if (!bs->file) {
182
return -EINVAL;
183
}
184
185
- if (!bdrv_is_read_only(bs)) {
186
- error_report("Opening dmg images without an explicit read-only=on "
187
- "option is deprecated. Future versions will refuse to "
188
- "open the image instead of automatically marking the "
189
- "image read-only.");
190
- ret = bdrv_set_read_only(bs, true, errp);
191
- if (ret < 0) {
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
}
37
--
247
--
38
2.13.6
248
2.19.1
39
249
40
250
diff view generated by jsdifflib
1
This adds the .bdrv_co_create driver callback to file, which enables
1
If read-only=off, but auto-read-only=on is given, open a read-write NBD
2
image creation over QMP.
2
connection if the server provides a read-write export, but instead of
3
erroring out for read-only exports, just degrade to read-only.
3
4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
7
---
8
qapi/block-core.json | 20 ++++++++++++-
8
block/nbd-client.c | 10 +++++-----
9
block/file-posix.c | 79 +++++++++++++++++++++++++++++++++++++---------------
9
1 file changed, 5 insertions(+), 5 deletions(-)
10
2 files changed, 75 insertions(+), 24 deletions(-)
11
10
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
11
diff --git a/block/nbd-client.c b/block/nbd-client.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
13
--- a/block/nbd-client.c
15
+++ b/qapi/block-core.json
14
+++ b/block/nbd-client.c
16
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
17
{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
16
logout("Failed to negotiate with the NBD server\n");
18
17
return ret;
19
##
20
+# @BlockdevCreateOptionsFile:
21
+#
22
+# Driver specific image creation options for file.
23
+#
24
+# @filename Filename for the new image file
25
+# @size Size of the virtual disk in bytes
26
+# @preallocation Preallocation mode for the new image (default: off)
27
+# @nocow Turn off copy-on-write (valid only on btrfs; default: off)
28
+#
29
+# Since: 2.12
30
+##
31
+{ 'struct': 'BlockdevCreateOptionsFile',
32
+ 'data': { 'filename': 'str',
33
+ 'size': 'size',
34
+ '*preallocation': 'PreallocMode',
35
+ '*nocow': 'bool' } }
36
+
37
+##
38
# @BlockdevQcow2Version:
39
#
40
# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2)
41
@@ -XXX,XX +XXX,XX @@
42
'bochs': 'BlockdevCreateNotSupported',
43
'cloop': 'BlockdevCreateNotSupported',
44
'dmg': 'BlockdevCreateNotSupported',
45
- 'file': 'BlockdevCreateNotSupported',
46
+ 'file': 'BlockdevCreateOptionsFile',
47
'ftp': 'BlockdevCreateNotSupported',
48
'ftps': 'BlockdevCreateNotSupported',
49
'gluster': 'BlockdevCreateNotSupported',
50
diff --git a/block/file-posix.c b/block/file-posix.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/block/file-posix.c
53
+++ b/block/file-posix.c
54
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
55
return (int64_t)st.st_blocks * 512;
56
}
57
58
-static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
59
- Error **errp)
60
+static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
61
{
62
+ BlockdevCreateOptionsFile *file_opts;
63
int fd;
64
int result = 0;
65
- int64_t total_size = 0;
66
- bool nocow = false;
67
- PreallocMode prealloc;
68
- char *buf = NULL;
69
- Error *local_err = NULL;
70
71
- strstart(filename, "file:", &filename);
72
+ /* Validate options and set default values */
73
+ assert(options->driver == BLOCKDEV_DRIVER_FILE);
74
+ file_opts = &options->u.file;
75
76
- /* Read out options */
77
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
78
- BDRV_SECTOR_SIZE);
79
- nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
80
- buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
81
- prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
82
- PREALLOC_MODE_OFF, &local_err);
83
- g_free(buf);
84
- if (local_err) {
85
- error_propagate(errp, local_err);
86
- result = -EINVAL;
87
- goto out;
88
+ if (!file_opts->has_nocow) {
89
+ file_opts->nocow = false;
90
+ }
91
+ if (!file_opts->has_preallocation) {
92
+ file_opts->preallocation = PREALLOC_MODE_OFF;
93
}
18
}
94
19
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
95
- fd = qemu_open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
20
- !bdrv_is_read_only(bs)) {
96
+ /* Create file */
21
- error_setg(errp,
97
+ fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
22
- "request for write access conflicts with read-only export");
98
0644);
23
- return -EACCES;
99
if (fd < 0) {
24
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
100
result = -errno;
25
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
101
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
26
+ if (ret < 0) {
102
goto out;
27
+ return ret;
28
+ }
103
}
29
}
104
30
if (client->info.flags & NBD_FLAG_SEND_FUA) {
105
- if (nocow) {
31
bs->supported_write_flags = BDRV_REQ_FUA;
106
+ if (file_opts->nocow) {
107
#ifdef __linux__
108
/* Set NOCOW flag to solve performance issue on fs like btrfs.
109
* This is an optimisation. The FS_IOC_SETFLAGS ioctl return value
110
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
111
#endif
112
}
113
114
- result = raw_regular_truncate(fd, total_size, prealloc, errp);
115
+ result = raw_regular_truncate(fd, file_opts->size, file_opts->preallocation,
116
+ errp);
117
if (result < 0) {
118
goto out_close;
119
}
120
@@ -XXX,XX +XXX,XX @@ out:
121
return result;
122
}
123
124
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
125
+ Error **errp)
126
+{
127
+ BlockdevCreateOptions options;
128
+ int64_t total_size = 0;
129
+ bool nocow = false;
130
+ PreallocMode prealloc;
131
+ char *buf = NULL;
132
+ Error *local_err = NULL;
133
+
134
+ /* Skip file: protocol prefix */
135
+ strstart(filename, "file:", &filename);
136
+
137
+ /* Read out options */
138
+ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
139
+ BDRV_SECTOR_SIZE);
140
+ nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
141
+ buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
142
+ prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
143
+ PREALLOC_MODE_OFF, &local_err);
144
+ g_free(buf);
145
+ if (local_err) {
146
+ error_propagate(errp, local_err);
147
+ return -EINVAL;
148
+ }
149
+
150
+ options = (BlockdevCreateOptions) {
151
+ .driver = BLOCKDEV_DRIVER_FILE,
152
+ .u.file = {
153
+ .filename = (char *) filename,
154
+ .size = total_size,
155
+ .has_preallocation = true,
156
+ .preallocation = prealloc,
157
+ .has_nocow = true,
158
+ .nocow = nocow,
159
+ },
160
+ };
161
+ return raw_co_create(&options, errp);
162
+}
163
+
164
/*
165
* Find allocation range in @bs around offset @start.
166
* May change underlying file descriptor's file offset.
167
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
168
.bdrv_reopen_commit = raw_reopen_commit,
169
.bdrv_reopen_abort = raw_reopen_abort,
170
.bdrv_close = raw_close,
171
+ .bdrv_co_create = raw_co_create,
172
.bdrv_co_create_opts = raw_co_create_opts,
173
.bdrv_has_zero_init = bdrv_has_zero_init_1,
174
.bdrv_co_block_status = raw_co_block_status,
175
--
32
--
176
2.13.6
33
2.19.1
177
34
178
35
diff view generated by jsdifflib
1
If bdrv_truncate() is called, but the requested size is the same as
1
If read-only=off, but auto-read-only=on is given, open the file
2
before, don't call posix_fallocate(), which returns -EINVAL for length
2
read-write if we have the permissions, but instead of erroring out for
3
zero and would therefore make bdrv_truncate() fail.
3
read-only files, just degrade to read-only.
4
5
The problem can be triggered by creating a zero-sized raw image with
6
'falloc' preallocation mode.
7
4
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
11
---
7
---
12
block/file-posix.c | 14 +++++++++-----
8
block/file-posix.c | 19 ++++++++++++++++---
13
1 file changed, 9 insertions(+), 5 deletions(-)
9
1 file changed, 16 insertions(+), 3 deletions(-)
14
10
15
diff --git a/block/file-posix.c b/block/file-posix.c
11
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
13
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
14
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static int raw_regular_truncate(int fd, int64_t offset, PreallocMode prealloc,
15
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
20
* file systems that do not support fallocate(), trying to check if a
16
21
* block is allocated before allocating it, so don't do that here.
17
s->fd = -1;
22
*/
18
fd = qemu_open(filename, s->open_flags, 0644);
23
- result = -posix_fallocate(fd, current_length, offset - current_length);
19
- if (fd < 0) {
24
- if (result != 0) {
20
- ret = -errno;
25
- /* posix_fallocate() doesn't set errno. */
21
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
26
- error_setg_errno(errp, -result,
22
+ ret = fd < 0 ? -errno : 0;
27
- "Could not preallocate new data");
23
+
28
+ if (offset != current_length) {
24
+ if (ret == -EACCES || ret == -EROFS) {
29
+ result = -posix_fallocate(fd, current_length, offset - current_length);
25
+ /* Try to degrade to read-only, but if it doesn't work, still use the
30
+ if (result != 0) {
26
+ * normal error message. */
31
+ /* posix_fallocate() doesn't set errno. */
27
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
32
+ error_setg_errno(errp, -result,
28
+ bdrv_flags &= ~BDRV_O_RDWR;
33
+ "Could not preallocate new data");
29
+ raw_parse_flags(bdrv_flags, &s->open_flags);
34
+ }
30
+ assert(!(s->open_flags & O_CREAT));
35
+ } else {
31
+ fd = qemu_open(filename, s->open_flags);
36
+ result = 0;
32
+ ret = fd < 0 ? -errno : 0;
33
+ }
34
+ }
35
+
36
+ if (ret < 0) {
37
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
38
if (ret == -EROFS) {
39
ret = -EACCES;
37
}
40
}
38
goto out;
39
#endif
40
--
41
--
41
2.13.6
42
2.19.1
42
43
43
44
diff view generated by jsdifflib
1
The "redundancy" option for Sheepdog image creation is currently a
1
If read-only=off, but auto-read-only=on is given, just degrade to
2
string that can encode one or two integers depending on its format,
2
read-only.
3
which at the same time implicitly selects a mode.
4
5
This patch turns it into a QAPI union and converts the string into such
6
a QAPI object before interpreting the values.
7
3
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
10
---
6
---
11
qapi/block-core.json | 45 +++++++++++++++++++++++++
7
block/curl.c | 8 ++++----
12
block/sheepdog.c | 94 +++++++++++++++++++++++++++++++++++++---------------
8
1 file changed, 4 insertions(+), 4 deletions(-)
13
2 files changed, 112 insertions(+), 27 deletions(-)
14
9
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
10
diff --git a/block/curl.c b/block/curl.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/qapi/block-core.json
12
--- a/block/curl.c
18
+++ b/qapi/block-core.json
13
+++ b/block/curl.c
19
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
20
'*cluster-size' : 'size' } }
15
const char *protocol_delimiter;
21
16
int ret;
22
##
17
23
+# @SheepdogRedundancyType:
18
-
24
+#
19
- if (flags & BDRV_O_RDWR) {
25
+# @full Create a fully replicated vdi with x copies
20
- error_setg(errp, "curl block device does not support writes");
26
+# @erasure-coded Create an erasure coded vdi with x data strips and
21
- return -EROFS;
27
+# y parity strips
22
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
28
+#
23
+ errp);
29
+# Since: 2.12
30
+##
31
+{ 'enum': 'SheepdogRedundancyType',
32
+ 'data': [ 'full', 'erasure-coded' ] }
33
+
34
+##
35
+# @SheepdogRedundancyFull:
36
+#
37
+# @copies Number of copies to use (between 1 and 31)
38
+#
39
+# Since: 2.12
40
+##
41
+{ 'struct': 'SheepdogRedundancyFull',
42
+ 'data': { 'copies': 'int' }}
43
+
44
+##
45
+# @SheepdogRedundancyErasureCoded:
46
+#
47
+# @data-strips Number of data strips to use (one of {2,4,8,16})
48
+# @parity-strips Number of parity strips to use (between 1 and 15)
49
+#
50
+# Since: 2.12
51
+##
52
+{ 'struct': 'SheepdogRedundancyErasureCoded',
53
+ 'data': { 'data-strips': 'int',
54
+ 'parity-strips': 'int' }}
55
+
56
+##
57
+# @SheepdogRedundancy:
58
+#
59
+# Since: 2.12
60
+##
61
+{ 'union': 'SheepdogRedundancy',
62
+ 'base': { 'type': 'SheepdogRedundancyType' },
63
+ 'discriminator': 'type',
64
+ 'data': { 'full': 'SheepdogRedundancyFull',
65
+ 'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
66
+
67
+##
68
# @BlockdevCreateNotSupported:
69
#
70
# This is used for all drivers that don't support creating images.
71
diff --git a/block/sheepdog.c b/block/sheepdog.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/block/sheepdog.c
74
+++ b/block/sheepdog.c
75
@@ -XXX,XX +XXX,XX @@ out_with_err_set:
76
return ret;
77
}
78
79
+static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
80
+{
81
+ struct SheepdogInode *inode = &s->inode;
82
+
83
+ switch (opt->type) {
84
+ case SHEEPDOG_REDUNDANCY_TYPE_FULL:
85
+ if (opt->u.full.copies > SD_MAX_COPIES || opt->u.full.copies < 1) {
86
+ return -EINVAL;
87
+ }
88
+ inode->copy_policy = 0;
89
+ inode->nr_copies = opt->u.full.copies;
90
+ return 0;
91
+
92
+ case SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED:
93
+ {
94
+ int64_t copy = opt->u.erasure_coded.data_strips;
95
+ int64_t parity = opt->u.erasure_coded.parity_strips;
96
+
97
+ if (copy != 2 && copy != 4 && copy != 8 && copy != 16) {
98
+ return -EINVAL;
99
+ }
100
+
101
+ if (parity >= SD_EC_MAX_STRIP || parity < 1) {
102
+ return -EINVAL;
103
+ }
104
+
105
+ /*
106
+ * 4 bits for parity and 4 bits for data.
107
+ * We have to compress upper data bits because it can't represent 16
108
+ */
109
+ inode->copy_policy = ((copy / 2) << 4) + parity;
110
+ inode->nr_copies = copy + parity;
111
+ return 0;
112
+ }
113
+
114
+ default:
115
+ g_assert_not_reached();
116
+ }
117
+
118
+ return -EINVAL;
119
+}
120
+
121
/*
122
* Sheepdog support two kinds of redundancy, full replication and erasure
123
* coding.
124
@@ -XXX,XX +XXX,XX @@ out_with_err_set:
125
* # create a erasure coded vdi with x data strips and y parity strips
126
* -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
127
*/
128
-static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
129
+static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
130
{
131
- struct SheepdogInode *inode = &s->inode;
132
+ struct SheepdogRedundancy redundancy;
133
const char *n1, *n2;
134
long copy, parity;
135
char p[10];
136
+ int ret;
137
138
pstrcpy(p, sizeof(p), opt);
139
n1 = strtok(p, ":");
140
@@ -XXX,XX +XXX,XX @@ static int parse_redundancy(BDRVSheepdogState *s, const char *opt)
141
return -EINVAL;
142
}
143
144
- copy = strtol(n1, NULL, 10);
145
- /* FIXME fix error checking by switching to qemu_strtol() */
146
- if (copy > SD_MAX_COPIES || copy < 1) {
147
- return -EINVAL;
148
- }
149
- if (!n2) {
150
- inode->copy_policy = 0;
151
- inode->nr_copies = copy;
152
- return 0;
153
+ ret = qemu_strtol(n1, NULL, 10, &copy);
154
+ if (ret < 0) {
24
+ if (ret < 0) {
155
+ return ret;
25
+ return ret;
156
}
26
}
157
27
158
- if (copy != 2 && copy != 4 && copy != 8 && copy != 16) {
28
if (!libcurl_initialized) {
159
- return -EINVAL;
160
- }
161
+ if (!n2) {
162
+ redundancy = (SheepdogRedundancy) {
163
+ .type = SHEEPDOG_REDUNDANCY_TYPE_FULL,
164
+ .u.full.copies = copy,
165
+ };
166
+ } else {
167
+ ret = qemu_strtol(n2, NULL, 10, &parity);
168
+ if (ret < 0) {
169
+ return ret;
170
+ }
171
172
- parity = strtol(n2, NULL, 10);
173
- /* FIXME fix error checking by switching to qemu_strtol() */
174
- if (parity >= SD_EC_MAX_STRIP || parity < 1) {
175
- return -EINVAL;
176
+ redundancy = (SheepdogRedundancy) {
177
+ .type = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
178
+ .u.erasure_coded = {
179
+ .data_strips = copy,
180
+ .parity_strips = parity,
181
+ },
182
+ };
183
}
184
185
- /*
186
- * 4 bits for parity and 4 bits for data.
187
- * We have to compress upper data bits because it can't represent 16
188
- */
189
- inode->copy_policy = ((copy / 2) << 4) + parity;
190
- inode->nr_copies = copy + parity;
191
-
192
- return 0;
193
+ return parse_redundancy(s, &redundancy);
194
}
195
196
static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
197
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
198
g_free(buf);
199
buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
200
if (buf) {
201
- ret = parse_redundancy(s, buf);
202
+ ret = parse_redundancy_str(s, buf);
203
if (ret < 0) {
204
error_setg(errp, "Invalid redundancy mode: '%s'", buf);
205
goto out;
206
--
29
--
207
2.13.6
30
2.19.1
208
31
209
32
diff view generated by jsdifflib
1
This adds the .bdrv_co_create driver callback to gluster, which enables
1
If read-only=off, but auto-read-only=on is given, open the file
2
image creation over QMP.
2
read-write if we have the permissions, but instead of erroring out for
3
read-only files, just degrade to read-only.
3
4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Niels de Vos <ndevos@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
7
---
8
qapi/block-core.json | 18 ++++++-
8
block/gluster.c | 12 ++++++++++--
9
block/gluster.c | 135 ++++++++++++++++++++++++++++++++++-----------------
9
1 file changed, 10 insertions(+), 2 deletions(-)
10
2 files changed, 108 insertions(+), 45 deletions(-)
11
10
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
17
'*nocow': 'bool' } }
18
19
##
20
+# @BlockdevCreateOptionsGluster:
21
+#
22
+# Driver specific image creation options for gluster.
23
+#
24
+# @location Where to store the new image file
25
+# @size Size of the virtual disk in bytes
26
+# @preallocation Preallocation mode for the new image (default: off)
27
+#
28
+# Since: 2.12
29
+##
30
+{ 'struct': 'BlockdevCreateOptionsGluster',
31
+ 'data': { 'location': 'BlockdevOptionsGluster',
32
+ 'size': 'size',
33
+ '*preallocation': 'PreallocMode' } }
34
+
35
+##
36
# @BlockdevQcow2Version:
37
#
38
# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2)
39
@@ -XXX,XX +XXX,XX @@
40
'file': 'BlockdevCreateOptionsFile',
41
'ftp': 'BlockdevCreateNotSupported',
42
'ftps': 'BlockdevCreateNotSupported',
43
- 'gluster': 'BlockdevCreateNotSupported',
44
+ 'gluster': 'BlockdevCreateOptionsGluster',
45
'host_cdrom': 'BlockdevCreateNotSupported',
46
'host_device': 'BlockdevCreateNotSupported',
47
'http': 'BlockdevCreateNotSupported',
48
diff --git a/block/gluster.c b/block/gluster.c
11
diff --git a/block/gluster.c b/block/gluster.c
49
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
50
--- a/block/gluster.c
13
--- a/block/gluster.c
51
+++ b/block/gluster.c
14
+++ b/block/gluster.c
52
@@ -XXX,XX +XXX,XX @@ out:
15
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
53
return -errno;
16
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
54
}
17
55
18
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
56
-static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
19
- if (!s->fd) {
57
- const char *filename,
20
- ret = -errno;
58
- QDict *options, Error **errp)
21
+ ret = s->fd ? 0 : -errno;
59
+/* Converts options given in @filename and the @options QDict into the QAPI
60
+ * object @gconf. */
61
+static int qemu_gluster_parse(BlockdevOptionsGluster *gconf,
62
+ const char *filename,
63
+ QDict *options, Error **errp)
64
{
65
int ret;
66
if (filename) {
67
@@ -XXX,XX +XXX,XX @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
68
"[host[:port]]volume/path[?socket=...]"
69
"[,file.debug=N]"
70
"[,file.logfile=/path/filename.log]\n");
71
- errno = -ret;
72
- return NULL;
73
+ return ret;
74
}
75
} else {
76
ret = qemu_gluster_parse_json(gconf, options, errp);
77
@@ -XXX,XX +XXX,XX @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
78
"file.server.1.transport=unix,"
79
"file.server.1.socket=/var/run/glusterd.socket ..."
80
"\n");
81
- errno = -ret;
82
- return NULL;
83
+ return ret;
84
}
85
+ }
86
87
+ return 0;
88
+}
89
+
22
+
90
+static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
23
+ if (ret == -EACCES || ret == -EROFS) {
91
+ const char *filename,
24
+ /* Try to degrade to read-only, but if it doesn't work, still use the
92
+ QDict *options, Error **errp)
25
+ * normal error message. */
93
+{
26
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
94
+ int ret;
27
+ open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
95
+
28
+ s->fd = glfs_open(s->glfs, gconf->path, open_flags);
96
+ ret = qemu_gluster_parse(gconf, filename, options, errp);
29
+ ret = s->fd ? 0 : -errno;
97
+ if (ret < 0) {
30
+ }
98
+ errno = -ret;
99
+ return NULL;
100
}
31
}
101
32
102
return qemu_gluster_glfs_init(gconf, errp);
33
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
103
@@ -XXX,XX +XXX,XX @@ static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
104
return 0;
105
}
106
107
+static int qemu_gluster_co_create(BlockdevCreateOptions *options,
108
+ Error **errp)
109
+{
110
+ BlockdevCreateOptionsGluster *opts = &options->u.gluster;
111
+ struct glfs *glfs;
112
+ struct glfs_fd *fd = NULL;
113
+ int ret = 0;
114
+
115
+ assert(options->driver == BLOCKDEV_DRIVER_GLUSTER);
116
+
117
+ glfs = qemu_gluster_glfs_init(opts->location, errp);
118
+ if (!glfs) {
119
+ ret = -errno;
120
+ goto out;
121
+ }
122
+
123
+ fd = glfs_creat(glfs, opts->location->path,
124
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
125
+ if (!fd) {
126
+ ret = -errno;
127
+ goto out;
128
+ }
129
+
130
+ ret = qemu_gluster_do_truncate(fd, opts->size, opts->preallocation, errp);
131
+
132
+out:
133
+ if (fd) {
134
+ if (glfs_close(fd) != 0 && ret == 0) {
135
+ ret = -errno;
136
+ }
137
+ }
138
+ glfs_clear_preopened(glfs);
139
+ return ret;
140
+}
141
+
142
static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
143
QemuOpts *opts,
144
Error **errp)
145
{
146
+ BlockdevCreateOptions *options;
147
+ BlockdevCreateOptionsGluster *gopts;
148
BlockdevOptionsGluster *gconf;
149
- struct glfs *glfs;
150
- struct glfs_fd *fd = NULL;
151
- int ret = 0;
152
- PreallocMode prealloc;
153
- int64_t total_size = 0;
154
char *tmp = NULL;
155
Error *local_err = NULL;
156
+ int ret;
157
+
158
+ options = g_new0(BlockdevCreateOptions, 1);
159
+ options->driver = BLOCKDEV_DRIVER_GLUSTER;
160
+ gopts = &options->u.gluster;
161
162
gconf = g_new0(BlockdevOptionsGluster, 1);
163
+ gopts->location = gconf;
164
+
165
+ gopts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
166
+ BDRV_SECTOR_SIZE);
167
+
168
+ tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
169
+ gopts->preallocation = qapi_enum_parse(&PreallocMode_lookup, tmp,
170
+ PREALLOC_MODE_OFF, &local_err);
171
+ g_free(tmp);
172
+ if (local_err) {
173
+ error_propagate(errp, local_err);
174
+ ret = -EINVAL;
175
+ goto fail;
176
+ }
177
+
178
gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
179
GLUSTER_DEBUG_DEFAULT);
180
if (gconf->debug < 0) {
181
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_gluster_co_create_opts(const char *filename,
182
}
183
gconf->has_logfile = true;
184
185
- glfs = qemu_gluster_init(gconf, filename, NULL, errp);
186
- if (!glfs) {
187
- ret = -errno;
188
- goto out;
189
- }
190
-
191
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
192
- BDRV_SECTOR_SIZE);
193
-
194
- tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
195
- prealloc = qapi_enum_parse(&PreallocMode_lookup, tmp, PREALLOC_MODE_OFF,
196
- &local_err);
197
- g_free(tmp);
198
- if (local_err) {
199
- error_propagate(errp, local_err);
200
- ret = -EINVAL;
201
- goto out;
202
+ ret = qemu_gluster_parse(gconf, filename, NULL, errp);
203
+ if (ret < 0) {
204
+ goto fail;
205
}
206
207
- fd = glfs_creat(glfs, gconf->path,
208
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
209
- if (!fd) {
210
- ret = -errno;
211
- goto out;
212
+ ret = qemu_gluster_co_create(options, errp);
213
+ if (ret < 0) {
214
+ goto fail;
215
}
216
217
- ret = qemu_gluster_do_truncate(fd, total_size, prealloc, errp);
218
-
219
-out:
220
- if (fd) {
221
- if (glfs_close(fd) != 0 && ret == 0) {
222
- ret = -errno;
223
- }
224
- }
225
- qapi_free_BlockdevOptionsGluster(gconf);
226
- glfs_clear_preopened(glfs);
227
+ ret = 0;
228
+fail:
229
+ qapi_free_BlockdevCreateOptions(options);
230
return ret;
231
}
232
233
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster = {
234
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
235
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
236
.bdrv_close = qemu_gluster_close,
237
+ .bdrv_co_create = qemu_gluster_co_create,
238
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
239
.bdrv_getlength = qemu_gluster_getlength,
240
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
241
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_tcp = {
242
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
243
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
244
.bdrv_close = qemu_gluster_close,
245
+ .bdrv_co_create = qemu_gluster_co_create,
246
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
247
.bdrv_getlength = qemu_gluster_getlength,
248
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
249
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_unix = {
250
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
251
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
252
.bdrv_close = qemu_gluster_close,
253
+ .bdrv_co_create = qemu_gluster_co_create,
254
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
255
.bdrv_getlength = qemu_gluster_getlength,
256
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
257
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_gluster_rdma = {
258
.bdrv_reopen_commit = qemu_gluster_reopen_commit,
259
.bdrv_reopen_abort = qemu_gluster_reopen_abort,
260
.bdrv_close = qemu_gluster_close,
261
+ .bdrv_co_create = qemu_gluster_co_create,
262
.bdrv_co_create_opts = qemu_gluster_co_create_opts,
263
.bdrv_getlength = qemu_gluster_getlength,
264
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
265
--
34
--
266
2.13.6
35
2.19.1
267
36
268
37
diff view generated by jsdifflib
1
Once qcow2_co_create() can be called directly on an already existing
1
If read-only=off, but auto-read-only=on is given, open the volume
2
node, we must provide the 'full' and 'falloc' preallocation modes
2
read-write if we have the permissions, but instead of erroring out for
3
outside of creating the image on the protocol layer. Fortunately, we
3
read-only volumes, just degrade to read-only.
4
have preallocated truncate now which can provide this functionality.
5
4
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
---
7
---
10
block/qcow2.c | 28 +++++++++++++++++++---------
8
block/iscsi.c | 8 +++++---
11
1 file changed, 19 insertions(+), 9 deletions(-)
9
1 file changed, 5 insertions(+), 3 deletions(-)
12
10
13
diff --git a/block/qcow2.c b/block/qcow2.c
11
diff --git a/block/iscsi.c b/block/iscsi.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2.c
13
--- a/block/iscsi.c
16
+++ b/block/qcow2.c
14
+++ b/block/iscsi.c
17
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
15
@@ -XXX,XX +XXX,XX @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
18
}
16
/* Check the write protect flag of the LUN if we want to write */
19
blk_set_allow_write_beyond_eof(blk, true);
17
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
20
18
iscsilun->write_protected) {
21
+ /* Clear the protocol layer and preallocate it if necessary */
19
- error_setg(errp, "Cannot open a write protected LUN as read-write");
22
+ ret = blk_truncate(blk, 0, PREALLOC_MODE_OFF, errp);
20
- ret = -EACCES;
23
+ if (ret < 0) {
21
- goto out;
24
+ goto out;
22
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
25
+ }
26
+
27
+ if (qcow2_opts->preallocation == PREALLOC_MODE_FULL ||
28
+ qcow2_opts->preallocation == PREALLOC_MODE_FALLOC)
29
+ {
30
+ int64_t prealloc_size =
31
+ qcow2_calc_prealloc_size(qcow2_opts->size, cluster_size,
32
+ refcount_order);
33
+
34
+ ret = blk_truncate(blk, prealloc_size, qcow2_opts->preallocation, errp);
35
+ if (ret < 0) {
23
+ if (ret < 0) {
36
+ goto out;
24
+ goto out;
37
+ }
25
+ }
38
+ }
26
+ flags &= ~BDRV_O_RDWR;
39
+
27
}
40
/* Write the header */
28
41
QEMU_BUILD_BUG_ON((1 << MIN_CLUSTER_BITS) < sizeof(*header));
29
iscsi_readcapacity_sync(iscsilun, &local_err);
42
header = g_malloc0(cluster_size);
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
44
45
46
/* Create and open the file (protocol layer) */
47
- if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
48
- int refcount_order = ctz32(refcount_bits);
49
- int64_t prealloc_size =
50
- qcow2_calc_prealloc_size(size, cluster_size, refcount_order);
51
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
52
- qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_str(prealloc),
53
- &error_abort);
54
- }
55
-
56
ret = bdrv_create_file(filename, opts, errp);
57
if (ret < 0) {
58
goto finish;
59
--
30
--
60
2.13.6
31
2.19.1
61
32
62
33
diff view generated by jsdifflib
1
This adds the .bdrv_co_create driver callback to file-win32, which
1
While we want machine interfaces like -blockdev and QMP blockdev-add to
2
enables image creation over QMP.
2
add as little auto-detection as possible so that management tools are
3
explicit about their needs, -drive is a convenience option for human
4
users. Enabling auto-read-only=on by default there enables users to use
5
read-only images for read-only guest devices without having to specify
6
read-only=on explicitly. If they try to attach the image to a read-write
7
device, they will still get an error message.
3
8
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
11
---
8
block/file-win32.c | 47 ++++++++++++++++++++++++++++++++++++++---------
12
blockdev.c | 1 +
9
1 file changed, 38 insertions(+), 9 deletions(-)
13
1 file changed, 1 insertion(+)
10
14
11
diff --git a/block/file-win32.c b/block/file-win32.c
15
diff --git a/blockdev.c b/blockdev.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/block/file-win32.c
17
--- a/blockdev.c
14
+++ b/block/file-win32.c
18
+++ b/blockdev.c
15
@@ -XXX,XX +XXX,XX @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
19
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
16
return st.st_size;
20
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
17
}
21
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
18
22
read_only ? "on" : "off");
19
-static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
23
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
20
- Error **errp)
24
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
21
+static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
25
22
{
26
if (runstate_check(RUN_STATE_INMIGRATE)) {
23
+ BlockdevCreateOptionsFile *file_opts;
24
int fd;
25
- int64_t total_size = 0;
26
27
- strstart(filename, "file:", &filename);
28
+ assert(options->driver == BLOCKDEV_DRIVER_FILE);
29
+ file_opts = &options->u.file;
30
31
- /* Read out options */
32
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
33
- BDRV_SECTOR_SIZE);
34
+ if (file_opts->has_preallocation) {
35
+ error_setg(errp, "Preallocation is not supported on Windows");
36
+ return -EINVAL;
37
+ }
38
+ if (file_opts->has_nocow) {
39
+ error_setg(errp, "nocow is not supported on Windows");
40
+ return -EINVAL;
41
+ }
42
43
- fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
44
+ fd = qemu_open(file_opts->filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
45
0644);
46
if (fd < 0) {
47
error_setg_errno(errp, errno, "Could not create file");
48
return -EIO;
49
}
50
set_sparse(fd);
51
- ftruncate(fd, total_size);
52
+ ftruncate(fd, file_opts->size);
53
qemu_close(fd);
54
+
55
return 0;
56
}
57
58
+static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts,
59
+ Error **errp)
60
+{
61
+ BlockdevCreateOptions options;
62
+ int64_t total_size = 0;
63
+
64
+ strstart(filename, "file:", &filename);
65
+
66
+ /* Read out options */
67
+ total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
68
+ BDRV_SECTOR_SIZE);
69
+
70
+ options = (BlockdevCreateOptions) {
71
+ .driver = BLOCKDEV_DRIVER_FILE,
72
+ .u.file = {
73
+ .filename = (char *) filename,
74
+ .size = total_size,
75
+ .has_preallocation = false,
76
+ .has_nocow = false,
77
+ },
78
+ };
79
+ return raw_co_create(&options, errp);
80
+}
81
82
static QemuOptsList raw_create_opts = {
83
.name = "raw-create-opts",
84
--
27
--
85
2.13.6
28
2.19.1
86
29
87
30
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Max Reitz <mreitz@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
---
3
---
4
tests/qemu-iotests/207 | 261 +++++++++++++++++++++++++++++++++++++++++++++
4
tests/qemu-iotests/232 | 147 +++++++++++++++++++++++++++++++++++++
5
tests/qemu-iotests/207.out | 75 +++++++++++++
5
tests/qemu-iotests/232.out | 59 +++++++++++++++
6
tests/qemu-iotests/group | 1 +
6
tests/qemu-iotests/group | 1 +
7
3 files changed, 337 insertions(+)
7
3 files changed, 207 insertions(+)
8
create mode 100755 tests/qemu-iotests/207
8
create mode 100755 tests/qemu-iotests/232
9
create mode 100644 tests/qemu-iotests/207.out
9
create mode 100644 tests/qemu-iotests/232.out
10
10
11
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
11
diff --git a/tests/qemu-iotests/232 b/tests/qemu-iotests/232
12
new file mode 100755
12
new file mode 100755
13
index XXXXXXX..XXXXXXX
13
index XXXXXXX..XXXXXXX
14
--- /dev/null
14
--- /dev/null
15
+++ b/tests/qemu-iotests/207
15
+++ b/tests/qemu-iotests/232
16
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
17
+#!/bin/bash
17
+#!/bin/bash
18
+#
18
+#
19
+# Test ssh image creation
19
+# Test for auto-read-only
20
+#
20
+#
21
+# Copyright (C) 2018 Red Hat, Inc.
21
+# Copyright (C) 2018 Red Hat, Inc.
22
+#
22
+#
23
+# This program is free software; you can redistribute it and/or modify
23
+# 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
24
+# it under the terms of the GNU General Public License as published by
...
...
41
+echo "QA output created by $seq"
41
+echo "QA output created by $seq"
42
+
42
+
43
+here=`pwd`
43
+here=`pwd`
44
+status=1    # failure is the default!
44
+status=1    # failure is the default!
45
+
45
+
46
+_cleanup()
47
+{
48
+ _cleanup_test_img
49
+ rm -f $TEST_IMG.snap
50
+}
51
+trap "_cleanup; exit \$status" 0 1 2 3 15
52
+
46
+# get standard environment, filters and checks
53
+# get standard environment, filters and checks
47
+. ./common.rc
54
+. ./common.rc
48
+. ./common.filter
55
+. ./common.filter
49
+
56
+
50
+_supported_fmt raw
57
+_supported_fmt generic
51
+_supported_proto ssh
58
+_supported_proto file
52
+_supported_os Linux
59
+_supported_os Linux
53
+
60
+
54
+function do_run_qemu()
61
+function do_run_qemu()
55
+{
62
+{
56
+ echo Testing: "$@"
63
+ echo Testing: "$@"
57
+ $QEMU -nographic -qmp stdio -serial none "$@"
64
+ (
65
+ if ! test -t 0; then
66
+ while read cmd; do
67
+ echo $cmd
68
+ done
69
+ fi
70
+ echo quit
71
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
58
+ echo
72
+ echo
59
+}
73
+}
60
+
74
+
61
+function run_qemu()
75
+function run_qemu()
62
+{
76
+{
63
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
77
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp |
64
+ | _filter_qemu | _filter_imgfmt \
78
+ _filter_generated_node_ids | _filter_imgfmt
65
+ | _filter_actual_image_size
79
+}
66
+}
80
+
67
+
81
+function run_qemu_info_block()
68
+echo
82
+{
69
+echo "=== Successful image creation (defaults) ==="
83
+ echo "info block -n" | run_qemu "$@" | grep -e "(file" -e "QEMU_PROG"
70
+echo
84
+}
71
+
85
+
72
+run_qemu <<EOF
86
+size=128M
73
+{ "execute": "qmp_capabilities" }
87
+
74
+{ "execute": "x-blockdev-create",
88
+_make_test_img $size
75
+ "arguments": {
89
+
76
+ "driver": "ssh",
90
+echo
77
+ "location": {
91
+echo "=== -drive with read-write image: read-only/auto-read-only combinations ==="
78
+ "path": "$TEST_IMG_FILE",
92
+echo
79
+ "server": {
93
+
80
+ "host": "127.0.0.1",
94
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
81
+ "port": "22"
95
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
82
+ }
96
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
83
+ },
97
+echo
84
+ "size": 4194304
98
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
85
+ }
99
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
86
+}
100
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
87
+{ "execute": "quit" }
101
+echo
88
+EOF
102
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
89
+
103
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
90
+_img_info | _filter_img_info
104
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
91
+echo
105
+
92
+TEST_IMG=$TEST_IMG_FILE _img_info | _filter_img_info
106
+echo
93
+
107
+echo "=== -drive with read-only image: read-only/auto-read-only combinations ==="
94
+echo
108
+echo
95
+echo "=== Test host-key-check options ==="
109
+
96
+echo
110
+chmod a-w $TEST_IMG
97
+
111
+
98
+run_qemu <<EOF
112
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=off
99
+{ "execute": "qmp_capabilities" }
113
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on,auto-read-only=on
100
+{ "execute": "x-blockdev-create",
114
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=on
101
+ "arguments": {
115
+echo
102
+ "driver": "ssh",
116
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=off
103
+ "location": {
117
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off,auto-read-only=on
104
+ "path": "$TEST_IMG_FILE",
118
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,read-only=off
105
+ "server": {
119
+echo
106
+ "host": "127.0.0.1",
120
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=off
107
+ "port": "22"
121
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none,auto-read-only=on
108
+ },
122
+run_qemu_info_block -drive driver=file,file="$TEST_IMG",if=none
109
+ "host-key-check": {
123
+
110
+ "mode": "none"
124
+echo
111
+ }
125
+echo "=== -blockdev with read-write image: read-only/auto-read-only combinations ==="
112
+ },
126
+echo
113
+ "size": 8388608
127
+
114
+ }
128
+chmod a+w $TEST_IMG
115
+}
129
+
116
+{ "execute": "quit" }
130
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
117
+EOF
131
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
118
+
132
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
119
+_img_info | _filter_img_info
133
+echo
120
+
134
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
121
+run_qemu <<EOF
135
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
122
+{ "execute": "qmp_capabilities" }
136
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
123
+{ "execute": "x-blockdev-create",
137
+echo
124
+ "arguments": {
138
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
125
+ "driver": "ssh",
139
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
126
+ "location": {
140
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
127
+ "path": "$TEST_IMG_FILE",
141
+
128
+ "server": {
142
+echo
129
+ "host": "127.0.0.1",
143
+echo "=== -blockdev with read-only image: read-only/auto-read-only combinations ==="
130
+ "port": "22"
144
+echo
131
+ },
145
+
132
+ "host-key-check": {
146
+chmod a-w $TEST_IMG
133
+ "mode": "known_hosts"
147
+
134
+ }
148
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=off
135
+ },
149
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on,auto-read-only=on
136
+ "size": 4194304
150
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=on
137
+ }
151
+echo
138
+}
152
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=off
139
+{ "execute": "quit" }
153
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off,auto-read-only=on
140
+EOF
154
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,read-only=off
141
+
155
+echo
142
+_img_info | _filter_img_info
156
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=off
143
+
157
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0,auto-read-only=on
144
+
158
+run_qemu_info_block -blockdev driver=file,filename="$TEST_IMG",node-name=node0
145
+key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" |
146
+ cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1)
147
+
148
+run_qemu <<EOF
149
+{ "execute": "qmp_capabilities" }
150
+{ "execute": "x-blockdev-create",
151
+ "arguments": {
152
+ "driver": "ssh",
153
+ "location": {
154
+ "path": "$TEST_IMG_FILE",
155
+ "server": {
156
+ "host": "127.0.0.1",
157
+ "port": "22"
158
+ },
159
+ "host-key-check": {
160
+ "mode": "hash",
161
+ "type": "md5",
162
+ "hash": "wrong"
163
+ }
164
+ },
165
+ "size": 8388608
166
+ }
167
+}
168
+{ "execute": "x-blockdev-create",
169
+ "arguments": {
170
+ "driver": "ssh",
171
+ "location": {
172
+ "path": "$TEST_IMG_FILE",
173
+ "server": {
174
+ "host": "127.0.0.1",
175
+ "port": "22"
176
+ },
177
+ "host-key-check": {
178
+ "mode": "hash",
179
+ "type": "md5",
180
+ "hash": "$key"
181
+ }
182
+ },
183
+ "size": 8388608
184
+ }
185
+}
186
+{ "execute": "quit" }
187
+EOF
188
+
189
+_img_info | _filter_img_info
190
+
191
+
192
+key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" |
193
+ cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1)
194
+
195
+run_qemu <<EOF
196
+{ "execute": "qmp_capabilities" }
197
+{ "execute": "x-blockdev-create",
198
+ "arguments": {
199
+ "driver": "ssh",
200
+ "location": {
201
+ "path": "$TEST_IMG_FILE",
202
+ "server": {
203
+ "host": "127.0.0.1",
204
+ "port": "22"
205
+ },
206
+ "host-key-check": {
207
+ "mode": "hash",
208
+ "type": "sha1",
209
+ "hash": "wrong"
210
+ }
211
+ },
212
+ "size": 4194304
213
+ }
214
+}
215
+{ "execute": "x-blockdev-create",
216
+ "arguments": {
217
+ "driver": "ssh",
218
+ "location": {
219
+ "path": "$TEST_IMG_FILE",
220
+ "server": {
221
+ "host": "127.0.0.1",
222
+ "port": "22"
223
+ },
224
+ "host-key-check": {
225
+ "mode": "hash",
226
+ "type": "sha1",
227
+ "hash": "$key"
228
+ }
229
+ },
230
+ "size": 4194304
231
+ }
232
+}
233
+{ "execute": "quit" }
234
+EOF
235
+
236
+_img_info | _filter_img_info
237
+
238
+echo
239
+echo "=== Invalid path and user ==="
240
+echo
241
+
242
+run_qemu <<EOF
243
+{ "execute": "qmp_capabilities" }
244
+{ "execute": "x-blockdev-create",
245
+ "arguments": {
246
+ "driver": "ssh",
247
+ "location": {
248
+ "path": "/this/is/not/an/existing/path",
249
+ "server": {
250
+ "host": "127.0.0.1",
251
+ "port": "22"
252
+ }
253
+ },
254
+ "size": 4194304
255
+ }
256
+}
257
+{ "execute": "x-blockdev-create",
258
+ "arguments": {
259
+ "driver": "ssh",
260
+ "location": {
261
+ "path": "$TEST_IMG_FILE",
262
+ "user": "invalid user",
263
+ "server": {
264
+ "host": "127.0.0.1",
265
+ "port": "22"
266
+ }
267
+ },
268
+ "size": 4194304
269
+ }
270
+}
271
+{ "execute": "quit" }
272
+EOF
273
+
159
+
274
+# success, all done
160
+# success, all done
275
+echo "*** done"
161
+echo "*** done"
276
+rm -f $seq.full
162
+rm -f $seq.full
277
+status=0
163
+status=0
278
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
164
diff --git a/tests/qemu-iotests/232.out b/tests/qemu-iotests/232.out
279
new file mode 100644
165
new file mode 100644
280
index XXXXXXX..XXXXXXX
166
index XXXXXXX..XXXXXXX
281
--- /dev/null
167
--- /dev/null
282
+++ b/tests/qemu-iotests/207.out
168
+++ b/tests/qemu-iotests/232.out
283
@@ -XXX,XX +XXX,XX @@
169
@@ -XXX,XX +XXX,XX @@
284
+QA output created by 207
170
+QA output created by 232
285
+
171
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
286
+=== Successful image creation (defaults) ===
172
+
287
+
173
+=== -drive with read-write image: read-only/auto-read-only combinations ===
288
+Testing:
174
+
289
+QMP_VERSION
175
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
290
+{"return": {}}
176
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
291
+{"return": {}}
177
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
292
+{"return": {}}
178
+
293
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
179
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
294
+
180
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
295
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
181
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
296
+file format: IMGFMT
182
+
297
+virtual size: 4.0M (4194304 bytes)
183
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
298
+
184
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
299
+image: TEST_DIR/t.IMGFMT
185
+NODE_NAME: TEST_DIR/t.IMGFMT (file)
300
+file format: IMGFMT
186
+
301
+virtual size: 4.0M (4194304 bytes)
187
+=== -drive with read-only image: read-only/auto-read-only combinations ===
302
+
188
+
303
+=== Test host-key-check options ===
189
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
304
+
190
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
305
+Testing:
191
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
306
+QMP_VERSION
192
+
307
+{"return": {}}
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
308
+{"return": {}}
194
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
309
+{"return": {}}
195
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
310
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
196
+
311
+
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
312
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
198
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
313
+file format: IMGFMT
199
+NODE_NAME: TEST_DIR/t.IMGFMT (file, read-only)
314
+virtual size: 8.0M (8388608 bytes)
200
+
315
+Testing:
201
+=== -blockdev with read-write image: read-only/auto-read-only combinations ===
316
+QMP_VERSION
202
+
317
+{"return": {}}
203
+node0: TEST_DIR/t.IMGFMT (file, read-only)
318
+{"return": {}}
204
+node0: TEST_DIR/t.IMGFMT (file, read-only)
319
+{"return": {}}
205
+node0: TEST_DIR/t.IMGFMT (file, read-only)
320
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
206
+
321
+
207
+node0: TEST_DIR/t.IMGFMT (file)
322
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
208
+node0: TEST_DIR/t.IMGFMT (file)
323
+file format: IMGFMT
209
+node0: TEST_DIR/t.IMGFMT (file)
324
+virtual size: 4.0M (4194304 bytes)
210
+
325
+Testing:
211
+node0: TEST_DIR/t.IMGFMT (file)
326
+QMP_VERSION
212
+node0: TEST_DIR/t.IMGFMT (file)
327
+{"return": {}}
213
+node0: TEST_DIR/t.IMGFMT (file)
328
+{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
214
+
329
+{"return": {}}
215
+=== -blockdev with read-only image: read-only/auto-read-only combinations ===
330
+{"return": {}}
216
+
331
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
217
+node0: TEST_DIR/t.IMGFMT (file, read-only)
332
+
218
+node0: TEST_DIR/t.IMGFMT (file, read-only)
333
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
219
+node0: TEST_DIR/t.IMGFMT (file, read-only)
334
+file format: IMGFMT
220
+
335
+virtual size: 8.0M (8388608 bytes)
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
336
+Testing:
222
+node0: TEST_DIR/t.IMGFMT (file, read-only)
337
+QMP_VERSION
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
338
+{"return": {}}
224
+
339
+{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
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
340
+{"return": {}}
226
+node0: TEST_DIR/t.IMGFMT (file, read-only)
341
+{"return": {}}
227
+QEMU_PROG: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
342
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
343
+
344
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
345
+file format: IMGFMT
346
+virtual size: 4.0M (4194304 bytes)
347
+
348
+=== Invalid path and user ===
349
+
350
+Testing:
351
+QMP_VERSION
352
+{"return": {}}
353
+{"error": {"class": "GenericError", "desc": "failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)"}}
354
+{"error": {"class": "GenericError", "desc": "failed to authenticate using publickey authentication and the identities held by your ssh-agent"}}
355
+{"return": {}}
356
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
357
+
358
+*** done
228
+*** done
359
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
229
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
360
index XXXXXXX..XXXXXXX 100644
230
index XXXXXXX..XXXXXXX 100644
361
--- a/tests/qemu-iotests/group
231
--- a/tests/qemu-iotests/group
362
+++ b/tests/qemu-iotests/group
232
+++ b/tests/qemu-iotests/group
363
@@ -XXX,XX +XXX,XX @@
233
@@ -XXX,XX +XXX,XX @@
364
204 rw auto quick
234
227 auto quick
365
205 rw auto quick
235
229 auto quick
366
206 rw auto
236
231 auto quick
367
+207 rw auto
237
+232 auto quick
368
--
238
--
369
2.13.6
239
2.19.1
370
240
371
241
diff view generated by jsdifflib
1
This allows, given a QemuOpts for a QemuOptsList that was merged from
1
From: Max Reitz <mreitz@redhat.com>
2
multiple QemuOptsList, to only consider those options that exist in one
3
specific list. Block drivers need this to separate format-layer create
4
options from protocol-level options.
5
2
3
This adds some whitespace into the option help (including indentation)
4
and puts angle brackets around the type names. Furthermore, the list
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
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
---
23
---
10
include/qemu/option.h | 2 ++
24
include/qemu/option.h | 2 +-
11
util/qemu-option.c | 42 +++++++++++++++++++++++++++++++++++++-----
25
qemu-img.c | 4 +-
12
2 files changed, 39 insertions(+), 5 deletions(-)
26
util/qemu-option.c | 32 +-
27
tests/qemu-iotests/082.out | 956 ++++++++++++++++++-------------------
28
4 files changed, 507 insertions(+), 487 deletions(-)
13
29
14
diff --git a/include/qemu/option.h b/include/qemu/option.h
30
diff --git a/include/qemu/option.h b/include/qemu/option.h
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/option.h
32
--- a/include/qemu/option.h
17
+++ b/include/qemu/option.h
33
+++ b/include/qemu/option.h
18
@@ -XXX,XX +XXX,XX @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
34
@@ -XXX,XX +XXX,XX @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts *opts, Error **errp);
19
int permit_abbrev);
35
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
20
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
36
void *opaque, Error **errp);
21
Error **errp);
37
void qemu_opts_print(QemuOpts *opts, const char *sep);
22
+QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
38
-void qemu_opts_print_help(QemuOptsList *list);
23
+ QemuOptsList *list, bool del);
39
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
24
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
40
void qemu_opts_free(QemuOptsList *list);
25
void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
41
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
26
42
43
diff --git a/qemu-img.c b/qemu-img.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/qemu-img.c
46
+++ b/qemu-img.c
47
@@ -XXX,XX +XXX,XX @@ static int print_block_option_help(const char *filename, const char *fmt)
48
}
49
50
printf("Supported options:\n");
51
- qemu_opts_print_help(create_opts);
52
+ qemu_opts_print_help(create_opts, false);
53
qemu_opts_free(create_opts);
54
return 0;
55
}
56
@@ -XXX,XX +XXX,XX @@ static int print_amend_option_help(const char *format)
57
assert(drv->create_opts);
58
59
printf("Creation options for '%s':\n", format);
60
- qemu_opts_print_help(drv->create_opts);
61
+ qemu_opts_print_help(drv->create_opts, false);
62
printf("\nNote that not all of these options may be amendable.\n");
63
return 0;
64
}
27
diff --git a/util/qemu-option.c b/util/qemu-option.c
65
diff --git a/util/qemu-option.c b/util/qemu-option.c
28
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
29
--- a/util/qemu-option.c
67
--- a/util/qemu-option.c
30
+++ b/util/qemu-option.c
68
+++ b/util/qemu-option.c
31
@@ -XXX,XX +XXX,XX @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
69
@@ -XXX,XX +XXX,XX @@ static const char *opt_type_to_string(enum QemuOptType type)
70
g_assert_not_reached();
32
}
71
}
33
72
34
/*
73
-void qemu_opts_print_help(QemuOptsList *list)
35
- * Convert from QemuOpts to QDict.
74
+/**
36
- * The QDict values are of type QString.
75
+ * Print the list of options available in the given list. If
37
+ * Convert from QemuOpts to QDict. The QDict values are of type QString.
76
+ * @print_caption is true, a caption (including the list name, if it
38
+ *
77
+ * exists) is printed. The options itself will be indented, so
39
+ * If @list is given, only add those options to the QDict that are contained in
78
+ * @print_caption should only be set to false if the caller prints its
40
+ * the list. If @del is true, any options added to the QDict are removed from
79
+ * own custom caption (so that the indentation makes sense).
41
+ * the QemuOpts, otherwise they remain there.
80
+ */
42
+ *
81
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
43
+ * If two options in @opts have the same name, they are processed in order
44
+ * so that the last one wins (consistent with the reverse iteration in
45
+ * qemu_opt_find()), but all of them are deleted if @del is true.
46
+ *
47
* TODO We'll want to use types appropriate for opt->desc->type, but
48
* this is enough for now.
49
*/
50
-QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
51
+QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
52
+ QemuOptsList *list, bool del)
53
{
82
{
54
- QemuOpt *opt;
83
QemuOptDesc *desc;
55
+ QemuOpt *opt, *next;
84
int i;
56
85
@@ -XXX,XX +XXX,XX @@ void qemu_opts_print_help(QemuOptsList *list)
57
if (!qdict) {
86
desc = list->desc;
58
qdict = qdict_new();
87
while (desc && desc->name) {
59
@@ -XXX,XX +XXX,XX @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
88
GString *str = g_string_new(NULL);
60
if (opts->id) {
89
- if (list->name) {
61
qdict_put_str(qdict, "id", opts->id);
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)
62
}
103
}
63
- QTAILQ_FOREACH(opt, &opts->head, next) {
104
64
+ QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next) {
105
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
65
+ if (list) {
106
+ if (print_caption && array->len > 0) {
66
+ QemuOptDesc *desc;
107
+ if (list->name) {
67
+ bool found = false;
108
+ printf("%s options:\n", list->name);
68
+ for (desc = list->desc; desc->name; desc++) {
109
+ } else {
69
+ if (!strcmp(desc->name, opt->name)) {
110
+ printf("Options:\n");
70
+ found = true;
71
+ break;
72
+ }
73
+ }
74
+ if (!found) {
75
+ continue;
76
+ }
77
+ }
111
+ }
78
qdict_put_str(qdict, opt->name, opt->str);
112
+ } else if (array->len == 0) {
79
+ if (del) {
113
+ if (list->name) {
80
+ qemu_opt_del(opt);
114
+ printf("There are no options for %s.\n", list->name);
115
+ } else {
116
+ printf("No options available.\n");
81
+ }
117
+ }
118
+ }
119
for (i = 0; i < array->len; i++) {
120
printf("%s\n", (char *)array->pdata[i]);
82
}
121
}
83
return qdict;
122
@@ -XXX,XX +XXX,XX @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
84
}
123
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
85
124
if (err) {
86
+/* Copy all options in a QemuOpts to the given QDict. See
125
if (invalidp && has_help_option(params)) {
87
+ * qemu_opts_to_qdict_filtered() for details. */
126
- qemu_opts_print_help(list);
88
+QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
127
+ qemu_opts_print_help(list, true);
89
+{
128
error_free(err);
90
+ return qemu_opts_to_qdict_filtered(opts, qdict, NULL, false);
129
} else {
91
+}
130
error_report_err(err);
92
+
131
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
93
/* Validate parsed opts against descriptions where no
132
index XXXXXXX..XXXXXXX 100644
94
* descriptions were provided in the QemuOptsList.
133
--- a/tests/qemu-iotests/082.out
95
*/
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
96
--
1221
--
97
2.13.6
1222
2.19.1
98
1223
99
1224
diff view generated by jsdifflib
1
From: "Daniel P. Berrange" <berrange@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
If the bdrv_reopen_prepare helper isn't provided, the qemu-img commit
3
Following the example of qemu_opts_print_help(), indent all entries in
4
command fails to re-open the base layer after committing changes into
4
the list of character devices.
5
it. Provide a no-op implementation for the LUKS driver, since there
6
is not any custom work that needs doing to re-open it.
7
5
8
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
block/crypto.c | 7 +++++++
10
chardev/char.c | 2 +-
12
1 file changed, 7 insertions(+)
11
1 file changed, 1 insertion(+), 1 deletion(-)
13
12
14
diff --git a/block/crypto.c b/block/crypto.c
13
diff --git a/chardev/char.c b/chardev/char.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/block/crypto.c
15
--- a/chardev/char.c
17
+++ b/block/crypto.c
16
+++ b/chardev/char.c
18
@@ -XXX,XX +XXX,XX @@ static void block_crypto_close(BlockDriverState *bs)
17
@@ -XXX,XX +XXX,XX @@ help_string_append(const char *name, void *opaque)
19
qcrypto_block_free(crypto->block);
18
{
19
GString *str = opaque;
20
21
- g_string_append_printf(str, "\n%s", name);
22
+ g_string_append_printf(str, "\n %s", name);
20
}
23
}
21
24
22
+static int block_crypto_reopen_prepare(BDRVReopenState *state,
25
static const char *chardev_alias_translate(const char *name)
23
+ BlockReopenQueue *queue, Error **errp)
24
+{
25
+ /* nothing needs checking */
26
+ return 0;
27
+}
28
29
/*
30
* 1 MB bounce buffer gives good performance / memory tradeoff
31
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_crypto_luks = {
32
.bdrv_truncate = block_crypto_truncate,
33
.create_opts = &block_crypto_create_opts_luks,
34
35
+ .bdrv_reopen_prepare = block_crypto_reopen_prepare,
36
.bdrv_refresh_limits = block_crypto_refresh_limits,
37
.bdrv_co_preadv = block_crypto_co_preadv,
38
.bdrv_co_pwritev = block_crypto_co_pwritev,
39
--
26
--
40
2.13.6
27
2.19.1
41
28
42
29
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This function iterates over all snapshots of a qcow2 file in order to
3
Just like in qemu_opts_print_help(), print the device name as a caption
4
expand all zero clusters, but it does not validate the snapshots' L1
4
instead of on every single line, indent all options, add angle brackets
5
tables first.
5
around types, and align the descriptions after 24 characters. Also,
6
separate the descriptions with " - " instead of putting them in
7
parentheses, because that is what we do everywhere else. This does look
8
a bit funny here because basically all bits have the description
9
"on/off", but funny does not mean it is less readable.
6
10
7
We now have a function to take care of this, so let's use it.
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
12
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
We can also take the opportunity to replace the sector-based
10
bdrv_read() with bdrv_pread().
11
12
Cc: Eric Blake <eblake@redhat.com>
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
14
---
17
block/qcow2-cluster.c | 24 +++++++++++++++++-------
15
qdev-monitor.c | 13 +++++++++++--
18
tests/qemu-iotests/080 | 2 ++
16
1 file changed, 11 insertions(+), 2 deletions(-)
19
tests/qemu-iotests/080.out | 4 ++++
20
3 files changed, 23 insertions(+), 7 deletions(-)
21
17
22
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
18
diff --git a/qdev-monitor.c b/qdev-monitor.c
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2-cluster.c
20
--- a/qdev-monitor.c
25
+++ b/block/qcow2-cluster.c
21
+++ b/qdev-monitor.c
26
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ int qdev_device_help(QemuOpts *opts)
27
#include "qemu/osdep.h"
23
goto error;
28
#include <zlib.h>
29
30
+#include "qapi/error.h"
31
#include "qemu-common.h"
32
#include "block/block_int.h"
33
#include "block/qcow2.h"
34
@@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
35
}
24
}
36
25
37
for (i = 0; i < s->nb_snapshots; i++) {
26
+ if (prop_list) {
38
- int l1_sectors = DIV_ROUND_UP(s->snapshots[i].l1_size *
27
+ out_printf("%s options:\n", driver);
39
- sizeof(uint64_t), BDRV_SECTOR_SIZE);
28
+ } else {
40
+ int l1_size2;
29
+ out_printf("There are no options for %s.\n", driver);
41
+ uint64_t *new_l1_table;
30
+ }
42
+ Error *local_err = NULL;
31
for (prop = prop_list; prop; prop = prop->next) {
43
+
32
- out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
44
+ ret = qcow2_validate_table(bs, s->snapshots[i].l1_table_offset,
33
+ int len;
45
+ s->snapshots[i].l1_size, sizeof(uint64_t),
34
+ out_printf(" %s=<%s>%n", prop->value->name, prop->value->type, &len);
46
+ QCOW_MAX_L1_SIZE, "Snapshot L1 table",
35
if (prop->value->has_description) {
47
+ &local_err);
36
- out_printf(" (%s)\n", prop->value->description);
48
+ if (ret < 0) {
37
+ if (len < 24) {
49
+ error_report_err(local_err);
38
+ out_printf("%*s", 24 - len, "");
50
+ goto fail;
39
+ }
51
+ }
40
+ out_printf(" - %s\n", prop->value->description);
52
41
} else {
53
- uint64_t *new_l1_table =
42
out_printf("\n");
54
- g_try_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
55
+ l1_size2 = s->snapshots[i].l1_size * sizeof(uint64_t);
56
+ new_l1_table = g_try_realloc(l1_table, l1_size2);
57
58
if (!new_l1_table) {
59
ret = -ENOMEM;
60
@@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
61
62
l1_table = new_l1_table;
63
64
- ret = bdrv_read(bs->file,
65
- s->snapshots[i].l1_table_offset / BDRV_SECTOR_SIZE,
66
- (void *)l1_table, l1_sectors);
67
+ ret = bdrv_pread(bs->file, s->snapshots[i].l1_table_offset,
68
+ l1_table, l1_size2);
69
if (ret < 0) {
70
goto fail;
71
}
43
}
72
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
73
index XXXXXXX..XXXXXXX 100755
74
--- a/tests/qemu-iotests/080
75
+++ b/tests/qemu-iotests/080
76
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
77
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
78
poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x00"
79
{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
80
+{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
81
82
echo
83
echo "== Invalid snapshot L1 table size =="
84
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
85
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
86
poke_file "$TEST_IMG" "$offset_snap1_l1_size" "\x10\x00\x00\x00"
87
{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
88
+{ $QEMU_IMG amend -o compat=0.10 $TEST_IMG; } 2>&1 | _filter_testdir
89
90
# success, all done
91
echo "*** done"
92
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
93
index XXXXXXX..XXXXXXX 100644
94
--- a/tests/qemu-iotests/080.out
95
+++ b/tests/qemu-iotests/080.out
96
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
97
wrote 512/512 bytes at offset 0
98
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
99
qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid
100
+qemu-img: Snapshot L1 table offset invalid
101
+qemu-img: Error while amending options: Invalid argument
102
103
== Invalid snapshot L1 table size ==
104
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
105
wrote 512/512 bytes at offset 0
106
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
107
qemu-img: Failed to load snapshot: Snapshot L1 table too large
108
+qemu-img: Snapshot L1 table too large
109
+qemu-img: Error while amending options: File too large
110
*** done
111
--
44
--
112
2.13.6
45
2.19.1
113
46
114
47
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
This function checks that the size of a snapshot's L1 table is not too
3
Just like in qemu_opts_print_help(), print the object name as a caption
4
large, but it doesn't validate the offset.
4
instead of on every single line, indent all options, add angle brackets
5
around types, and align the descriptions after 24 characters.
5
6
6
We now have a function to take care of this, so let's use it.
7
Also, indent every object name in the list of available objects.
7
8
8
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
---
12
block/qcow2-snapshot.c | 8 +++++---
13
vl.c | 13 ++++++++++---
13
tests/qemu-iotests/080 | 10 +++++++++-
14
1 file changed, 10 insertions(+), 3 deletions(-)
14
tests/qemu-iotests/080.out | 8 +++++++-
15
3 files changed, 21 insertions(+), 5 deletions(-)
16
15
17
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
16
diff --git a/vl.c b/vl.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-snapshot.c
18
--- a/vl.c
20
+++ b/block/qcow2-snapshot.c
19
+++ b/vl.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
20
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
22
sn = &s->snapshots[snapshot_index];
21
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
23
22
for (l = list; l != NULL; l = l->next) {
24
/* Allocate and read in the snapshot's L1 table */
23
ObjectClass *oc = OBJECT_CLASS(l->data);
25
- if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) {
24
- printf("%s\n", object_class_get_name(oc));
26
- error_setg(errp, "Snapshot L1 table too large");
25
+ printf(" %s\n", object_class_get_name(oc));
27
- return -EFBIG;
26
}
28
+ ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
27
g_slist_free(list);
29
+ sizeof(uint64_t), QCOW_MAX_L1_SIZE,
28
exit(0);
30
+ "Snapshot L1 table", errp);
29
@@ -XXX,XX +XXX,XX @@ static bool object_create_initial(const char *type, QemuOpts *opts)
31
+ if (ret < 0) {
30
}
32
+ return ret;
31
33
}
32
str = g_string_new(NULL);
34
new_l1_bytes = sn->l1_size * sizeof(uint64_t);
33
- g_string_append_printf(str, "%s.%s=%s", type,
35
new_l1_table = qemu_try_blockalign(bs->file->bs,
34
- prop->name, prop->type);
36
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
35
+ g_string_append_printf(str, " %s=<%s>", prop->name, prop->type);
37
index XXXXXXX..XXXXXXX 100755
36
if (prop->description) {
38
--- a/tests/qemu-iotests/080
37
+ if (str->len < 24) {
39
+++ b/tests/qemu-iotests/080
38
+ g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
40
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$offset_l2_table_0" "\x80\x00\x00\xff\xff\xff\x00\x00"
39
+ }
41
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
40
g_string_append_printf(str, " - %s", prop->description);
42
41
}
43
echo
42
g_ptr_array_add(array, g_string_free(str, false));
44
-echo "== Invalid snapshot L1 table =="
43
}
45
+echo "== Invalid snapshot L1 table offset =="
44
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
46
+_make_test_img 64M
45
+ if (array->len > 0) {
47
+{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
46
+ printf("%s options:\n", type);
48
+{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
47
+ } else {
49
+poke_file "$TEST_IMG" "$offset_snap1_l1_offset" "\x00\x00\x00\x00\x00\x40\x02\x00"
48
+ printf("There are no options for %s.\n", type);
50
+{ $QEMU_IMG convert -s test $TEST_IMG $TEST_IMG.snap; } 2>&1 | _filter_testdir
49
+ }
51
+
50
for (i = 0; i < array->len; i++) {
52
+echo
51
printf("%s\n", (char *)array->pdata[i]);
53
+echo "== Invalid snapshot L1 table size =="
52
}
54
_make_test_img 64M
55
{ $QEMU_IO -c "write 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
56
{ $QEMU_IMG snapshot -c test $TEST_IMG; } 2>&1 | _filter_testdir
57
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/080.out
60
+++ b/tests/qemu-iotests/080.out
61
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 0
62
qemu-img: Could not create snapshot 'test': -27 (File too large)
63
qemu-img: Could not create snapshot 'test': -11 (Resource temporarily unavailable)
64
65
-== Invalid snapshot L1 table ==
66
+== Invalid snapshot L1 table offset ==
67
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
68
+wrote 512/512 bytes at offset 0
69
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
70
+qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid
71
+
72
+== Invalid snapshot L1 table size ==
73
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
74
wrote 512/512 bytes at offset 0
75
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
76
--
53
--
77
2.13.6
54
2.19.1
78
55
79
56
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
They will be used to avoid recursively taking s->lock during
3
There is no good reason why there should be a newline in this
4
bdrv_open or bdrv_check.
4
description, so remove it.
5
5
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <1516279431-30424-7-git-send-email-pbonzini@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
10
---
11
block/qcow2.h | 2 ++
11
vl.c | 2 +-
12
block/qcow2-refcount.c | 28 ++++++++++++++++++++++++++++
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
block/qcow2.c | 20 ++++----------------
14
3 files changed, 34 insertions(+), 16 deletions(-)
15
13
16
diff --git a/block/qcow2.h b/block/qcow2.h
14
diff --git a/vl.c b/vl.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.h
16
--- a/vl.c
19
+++ b/block/qcow2.h
17
+++ b/vl.c
20
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry,
18
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_fw_cfg_opts = {
21
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
19
}, {
22
int64_t l1_table_offset, int l1_size, int addend);
20
.name = "file",
23
21
.type = QEMU_OPT_STRING,
24
+int coroutine_fn qcow2_flush_caches(BlockDriverState *bs);
22
- .help = "Sets the name of the file from which\n"
25
+int coroutine_fn qcow2_write_caches(BlockDriverState *bs);
23
+ .help = "Sets the name of the file from which "
26
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
24
"the fw_cfg blob will be loaded",
27
BdrvCheckMode fix);
25
}, {
28
26
.name = "string",
29
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2-refcount.c
32
+++ b/block/qcow2-refcount.c
33
@@ -XXX,XX +XXX,XX @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry,
34
}
35
}
36
37
+int coroutine_fn qcow2_write_caches(BlockDriverState *bs)
38
+{
39
+ BDRVQcow2State *s = bs->opaque;
40
+ int ret;
41
42
+ ret = qcow2_cache_write(bs, s->l2_table_cache);
43
+ if (ret < 0) {
44
+ return ret;
45
+ }
46
+
47
+ if (qcow2_need_accurate_refcounts(s)) {
48
+ ret = qcow2_cache_write(bs, s->refcount_block_cache);
49
+ if (ret < 0) {
50
+ return ret;
51
+ }
52
+ }
53
+
54
+ return 0;
55
+}
56
+
57
+int coroutine_fn qcow2_flush_caches(BlockDriverState *bs)
58
+{
59
+ int ret = qcow2_write_caches(bs);
60
+ if (ret < 0) {
61
+ return ret;
62
+ }
63
+
64
+ return bdrv_flush(bs->file->bs);
65
+}
66
67
/*********************************************************/
68
/* snapshots and image creation */
69
diff --git a/block/qcow2.c b/block/qcow2.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/block/qcow2.c
72
+++ b/block/qcow2.c
73
@@ -XXX,XX +XXX,XX @@ static int qcow2_mark_clean(BlockDriverState *bs)
74
75
s->incompatible_features &= ~QCOW2_INCOMPAT_DIRTY;
76
77
- ret = bdrv_flush(bs);
78
+ ret = qcow2_flush_caches(bs);
79
if (ret < 0) {
80
return ret;
81
}
82
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_consistent(BlockDriverState *bs)
83
BDRVQcow2State *s = bs->opaque;
84
85
if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) {
86
- int ret = bdrv_flush(bs);
87
+ int ret = qcow2_flush_caches(bs);
88
if (ret < 0) {
89
return ret;
90
}
91
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
92
int ret;
93
94
qemu_co_mutex_lock(&s->lock);
95
- ret = qcow2_cache_write(bs, s->l2_table_cache);
96
- if (ret < 0) {
97
- qemu_co_mutex_unlock(&s->lock);
98
- return ret;
99
- }
100
-
101
- if (qcow2_need_accurate_refcounts(s)) {
102
- ret = qcow2_cache_write(bs, s->refcount_block_cache);
103
- if (ret < 0) {
104
- qemu_co_mutex_unlock(&s->lock);
105
- return ret;
106
- }
107
- }
108
+ ret = qcow2_write_caches(bs);
109
qemu_co_mutex_unlock(&s->lock);
110
111
- return 0;
112
+ return ret;
113
}
114
115
static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
116
--
27
--
117
2.13.6
28
2.19.1
118
29
119
30
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
Suggested-by: Kevin Wolf <kwolf@redhat.com>
3
If an expression is used to define DEFAULT_CLUSTER_SIZE, when compiled,
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
it will be embedded as a literal expression in the binary (as the
5
Message-Id: <1516279431-30424-8-git-send-email-pbonzini@redhat.com>
5
default value) because it is stringified to mark the size of the default
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
value. Now this is fixed by using a defined number to define this value.
7
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
9
Reviewed-by: Stefan Weil <sw@weilnetz.de>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
11
---
9
include/block/block_int.h | 5 +++--
12
block/vdi.c | 4 ++--
10
block.c | 43 ++++++++++++++++++++++++++++++++++++++++---
13
1 file changed, 2 insertions(+), 2 deletions(-)
11
block/parallels.c | 17 +++++++++++------
12
block/qcow2.c | 23 +++++++++++++++++++----
13
block/qed-check.c | 1 +
14
block/qed-table.c | 26 +++++++++-----------------
15
block/qed.c | 13 +++++++++----
16
block/vdi.c | 6 +++---
17
block/vhdx.c | 7 ++++---
18
block/vmdk.c | 7 ++++---
19
10 files changed, 103 insertions(+), 45 deletions(-)
20
14
21
diff --git a/include/block/block_int.h b/include/block/block_int.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block_int.h
24
+++ b/include/block/block_int.h
25
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
26
* Returns 0 for completed check, -errno for internal errors.
27
* The check results are stored in result.
28
*/
29
- int (*bdrv_check)(BlockDriverState *bs, BdrvCheckResult *result,
30
- BdrvCheckMode fix);
31
+ int coroutine_fn (*bdrv_co_check)(BlockDriverState *bs,
32
+ BdrvCheckResult *result,
33
+ BdrvCheckMode fix);
34
35
int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts,
36
BlockDriverAmendStatusCB *status_cb,
37
diff --git a/block.c b/block.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block.c
40
+++ b/block.c
41
@@ -XXX,XX +XXX,XX @@ static void bdrv_delete(BlockDriverState *bs)
42
* free of errors) or -errno when an internal error occurred. The results of the
43
* check are stored in res.
44
*/
45
-int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix)
46
+static int coroutine_fn bdrv_co_check(BlockDriverState *bs,
47
+ BdrvCheckResult *res, BdrvCheckMode fix)
48
{
49
if (bs->drv == NULL) {
50
return -ENOMEDIUM;
51
}
52
- if (bs->drv->bdrv_check == NULL) {
53
+ if (bs->drv->bdrv_co_check == NULL) {
54
return -ENOTSUP;
55
}
56
57
memset(res, 0, sizeof(*res));
58
- return bs->drv->bdrv_check(bs, res, fix);
59
+ return bs->drv->bdrv_co_check(bs, res, fix);
60
+}
61
+
62
+typedef struct CheckCo {
63
+ BlockDriverState *bs;
64
+ BdrvCheckResult *res;
65
+ BdrvCheckMode fix;
66
+ int ret;
67
+} CheckCo;
68
+
69
+static void bdrv_check_co_entry(void *opaque)
70
+{
71
+ CheckCo *cco = opaque;
72
+ cco->ret = bdrv_co_check(cco->bs, cco->res, cco->fix);
73
+}
74
+
75
+int bdrv_check(BlockDriverState *bs,
76
+ BdrvCheckResult *res, BdrvCheckMode fix)
77
+{
78
+ Coroutine *co;
79
+ CheckCo cco = {
80
+ .bs = bs,
81
+ .res = res,
82
+ .ret = -EINPROGRESS,
83
+ .fix = fix,
84
+ };
85
+
86
+ if (qemu_in_coroutine()) {
87
+ /* Fast-path if already in coroutine context */
88
+ bdrv_check_co_entry(&cco);
89
+ } else {
90
+ co = qemu_coroutine_create(bdrv_check_co_entry, &cco);
91
+ qemu_coroutine_enter(co);
92
+ BDRV_POLL_WHILE(bs, cco.ret == -EINPROGRESS);
93
+ }
94
+
95
+ return cco.ret;
96
}
97
98
/*
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
104
}
105
106
107
-static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
108
- BdrvCheckMode fix)
109
+static int coroutine_fn parallels_co_check(BlockDriverState *bs,
110
+ BdrvCheckResult *res,
111
+ BdrvCheckMode fix)
112
{
113
BDRVParallelsState *s = bs->opaque;
114
int64_t size, prev_off, high_off;
115
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
116
return size;
117
}
118
119
+ qemu_co_mutex_lock(&s->lock);
120
if (s->header_unclean) {
121
fprintf(stderr, "%s image was not closed correctly\n",
122
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR");
123
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
124
prev_off = off;
125
}
126
127
+ ret = 0;
128
if (flush_bat) {
129
ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
130
if (ret < 0) {
131
res->check_errors++;
132
- return ret;
133
+ goto out;
134
}
135
}
136
137
@@ -XXX,XX +XXX,XX @@ static int parallels_check(BlockDriverState *bs, BdrvCheckResult *res,
138
if (ret < 0) {
139
error_report_err(local_err);
140
res->check_errors++;
141
- return ret;
142
+ goto out;
143
}
144
res->leaks_fixed += count;
145
}
146
}
147
148
- return 0;
149
+out:
150
+ qemu_co_mutex_unlock(&s->lock);
151
+ return ret;
152
}
153
154
155
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_parallels = {
156
.bdrv_co_writev = parallels_co_writev,
157
.supports_backing = true,
158
.bdrv_co_create_opts = parallels_co_create_opts,
159
- .bdrv_check = parallels_check,
160
+ .bdrv_co_check = parallels_co_check,
161
.create_opts = &parallels_create_opts,
162
};
163
164
diff --git a/block/qcow2.c b/block/qcow2.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/block/qcow2.c
167
+++ b/block/qcow2.c
168
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_consistent(BlockDriverState *bs)
169
return 0;
170
}
171
172
-static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
173
- BdrvCheckMode fix)
174
+static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
175
+ BdrvCheckResult *result,
176
+ BdrvCheckMode fix)
177
{
178
int ret = qcow2_check_refcounts(bs, result, fix);
179
if (ret < 0) {
180
@@ -XXX,XX +XXX,XX @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
181
return ret;
182
}
183
184
+static int coroutine_fn qcow2_co_check(BlockDriverState *bs,
185
+ BdrvCheckResult *result,
186
+ BdrvCheckMode fix)
187
+{
188
+ BDRVQcow2State *s = bs->opaque;
189
+ int ret;
190
+
191
+ qemu_co_mutex_lock(&s->lock);
192
+ ret = qcow2_co_check_locked(bs, result, fix);
193
+ qemu_co_mutex_unlock(&s->lock);
194
+ return ret;
195
+}
196
+
197
static int validate_table_offset(BlockDriverState *bs, uint64_t offset,
198
uint64_t entries, size_t entry_len)
199
{
200
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
201
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
202
BdrvCheckResult result = {0};
203
204
- ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
205
+ ret = qcow2_co_check_locked(bs, &result,
206
+ BDRV_FIX_ERRORS | BDRV_FIX_LEAKS);
207
if (ret < 0 || result.check_errors) {
208
if (ret >= 0) {
209
ret = -EIO;
210
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
211
.bdrv_inactivate = qcow2_inactivate,
212
213
.create_opts = &qcow2_create_opts,
214
- .bdrv_check = qcow2_check,
215
+ .bdrv_co_check = qcow2_co_check,
216
.bdrv_amend_options = qcow2_amend_options,
217
218
.bdrv_detach_aio_context = qcow2_detach_aio_context,
219
diff --git a/block/qed-check.c b/block/qed-check.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/block/qed-check.c
222
+++ b/block/qed-check.c
223
@@ -XXX,XX +XXX,XX @@ static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result)
224
qed_write_header_sync(s);
225
}
226
227
+/* Called with table_lock held. */
228
int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
229
{
230
QEDCheck check = {
231
diff --git a/block/qed-table.c b/block/qed-table.c
232
index XXXXXXX..XXXXXXX 100644
233
--- a/block/qed-table.c
234
+++ b/block/qed-table.c
235
@@ -XXX,XX +XXX,XX @@
236
#include "qed.h"
237
#include "qemu/bswap.h"
238
239
-/* Called either from qed_check or with table_lock held. */
240
+/* Called with table_lock held. */
241
static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
242
{
243
QEMUIOVector qiov;
244
@@ -XXX,XX +XXX,XX @@ static int qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table)
245
246
trace_qed_read_table(s, offset, table);
247
248
- if (qemu_in_coroutine()) {
249
- qemu_co_mutex_unlock(&s->table_lock);
250
- }
251
+ qemu_co_mutex_unlock(&s->table_lock);
252
ret = bdrv_preadv(s->bs->file, offset, &qiov);
253
- if (qemu_in_coroutine()) {
254
- qemu_co_mutex_lock(&s->table_lock);
255
- }
256
+ qemu_co_mutex_lock(&s->table_lock);
257
if (ret < 0) {
258
goto out;
259
}
260
@@ -XXX,XX +XXX,XX @@ out:
261
* @n: Number of elements
262
* @flush: Whether or not to sync to disk
263
*
264
- * Called either from qed_check or with table_lock held.
265
+ * Called with table_lock held.
266
*/
267
static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
268
unsigned int index, unsigned int n, bool flush)
269
@@ -XXX,XX +XXX,XX @@ static int qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
270
/* Adjust for offset into table */
271
offset += start * sizeof(uint64_t);
272
273
- if (qemu_in_coroutine()) {
274
- qemu_co_mutex_unlock(&s->table_lock);
275
- }
276
+ qemu_co_mutex_unlock(&s->table_lock);
277
ret = bdrv_pwritev(s->bs->file, offset, &qiov);
278
- if (qemu_in_coroutine()) {
279
- qemu_co_mutex_lock(&s->table_lock);
280
- }
281
+ qemu_co_mutex_lock(&s->table_lock);
282
trace_qed_write_table_cb(s, table, flush, ret);
283
if (ret < 0) {
284
goto out;
285
@@ -XXX,XX +XXX,XX @@ int qed_read_l1_table_sync(BDRVQEDState *s)
286
return qed_read_table(s, s->header.l1_table_offset, s->l1_table);
287
}
288
289
-/* Called either from qed_check or with table_lock held. */
290
+/* Called with table_lock held. */
291
int qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n)
292
{
293
BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
294
@@ -XXX,XX +XXX,XX @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
295
return qed_write_l1_table(s, index, n);
296
}
297
298
-/* Called either from qed_check or with table_lock held. */
299
+/* Called with table_lock held. */
300
int qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
301
{
302
int ret;
303
@@ -XXX,XX +XXX,XX @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
304
return qed_read_l2_table(s, request, offset);
305
}
306
307
-/* Called either from qed_check or with table_lock held. */
308
+/* Called with table_lock held. */
309
int qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
310
unsigned int index, unsigned int n, bool flush)
311
{
312
diff --git a/block/qed.c b/block/qed.c
313
index XXXXXXX..XXXXXXX 100644
314
--- a/block/qed.c
315
+++ b/block/qed.c
316
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
317
}
318
}
319
320
-static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
321
- BdrvCheckMode fix)
322
+static int bdrv_qed_co_check(BlockDriverState *bs, BdrvCheckResult *result,
323
+ BdrvCheckMode fix)
324
{
325
BDRVQEDState *s = bs->opaque;
326
+ int ret;
327
328
- return qed_check(s, result, !!fix);
329
+ qemu_co_mutex_lock(&s->table_lock);
330
+ ret = qed_check(s, result, !!fix);
331
+ qemu_co_mutex_unlock(&s->table_lock);
332
+
333
+ return ret;
334
}
335
336
static QemuOptsList qed_create_opts = {
337
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_qed = {
338
.bdrv_refresh_limits = bdrv_qed_refresh_limits,
339
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
340
.bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache,
341
- .bdrv_check = bdrv_qed_check,
342
+ .bdrv_co_check = bdrv_qed_co_check,
343
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
344
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
345
.bdrv_co_drain_begin = bdrv_qed_co_drain_begin,
346
diff --git a/block/vdi.c b/block/vdi.c
15
diff --git a/block/vdi.c b/block/vdi.c
347
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
348
--- a/block/vdi.c
17
--- a/block/vdi.c
349
+++ b/block/vdi.c
18
+++ b/block/vdi.c
350
@@ -XXX,XX +XXX,XX @@ static void vdi_header_print(VdiHeader *header)
19
@@ -XXX,XX +XXX,XX @@
351
}
20
#define BLOCK_OPT_STATIC "static"
352
#endif
21
353
22
#define SECTOR_SIZE 512
354
-static int vdi_check(BlockDriverState *bs, BdrvCheckResult *res,
23
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
355
- BdrvCheckMode fix)
24
+#define DEFAULT_CLUSTER_SIZE S_1MiB
356
+static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res,
25
357
+ BdrvCheckMode fix)
26
#if defined(CONFIG_VDI_DEBUG)
358
{
27
#define VDI_DEBUG 1
359
/* TODO: additional checks possible. */
28
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
360
BDRVVdiState *s = (BDRVVdiState *)bs->opaque;
29
goto fail;
361
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vdi = {
30
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
362
.bdrv_get_info = vdi_get_info,
31
error_setg(errp, "unsupported VDI image (block size %" PRIu32
363
32
- " is not %" PRIu64 ")",
364
.create_opts = &vdi_create_opts,
33
+ " is not %" PRIu32 ")",
365
- .bdrv_check = vdi_check,
34
header.block_size, DEFAULT_CLUSTER_SIZE);
366
+ .bdrv_co_check = vdi_co_check,
35
ret = -ENOTSUP;
367
};
36
goto fail;
368
369
static void bdrv_vdi_init(void)
370
diff --git a/block/vhdx.c b/block/vhdx.c
371
index XXXXXXX..XXXXXXX 100644
372
--- a/block/vhdx.c
373
+++ b/block/vhdx.c
374
@@ -XXX,XX +XXX,XX @@ exit:
375
* r/w and any log has already been replayed, so there is nothing (currently)
376
* for us to do here
377
*/
378
-static int vhdx_check(BlockDriverState *bs, BdrvCheckResult *result,
379
- BdrvCheckMode fix)
380
+static int coroutine_fn vhdx_co_check(BlockDriverState *bs,
381
+ BdrvCheckResult *result,
382
+ BdrvCheckMode fix)
383
{
384
BDRVVHDXState *s = bs->opaque;
385
386
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vhdx = {
387
.bdrv_co_writev = vhdx_co_writev,
388
.bdrv_co_create_opts = vhdx_co_create_opts,
389
.bdrv_get_info = vhdx_get_info,
390
- .bdrv_check = vhdx_check,
391
+ .bdrv_co_check = vhdx_co_check,
392
.bdrv_has_zero_init = bdrv_has_zero_init_1,
393
394
.create_opts = &vhdx_create_opts,
395
diff --git a/block/vmdk.c b/block/vmdk.c
396
index XXXXXXX..XXXXXXX 100644
397
--- a/block/vmdk.c
398
+++ b/block/vmdk.c
399
@@ -XXX,XX +XXX,XX @@ static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent)
400
return info;
401
}
402
403
-static int vmdk_check(BlockDriverState *bs, BdrvCheckResult *result,
404
- BdrvCheckMode fix)
405
+static int coroutine_fn vmdk_co_check(BlockDriverState *bs,
406
+ BdrvCheckResult *result,
407
+ BdrvCheckMode fix)
408
{
409
BDRVVmdkState *s = bs->opaque;
410
VmdkExtent *extent = NULL;
411
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vmdk = {
412
.instance_size = sizeof(BDRVVmdkState),
413
.bdrv_probe = vmdk_probe,
414
.bdrv_open = vmdk_open,
415
- .bdrv_check = vmdk_check,
416
+ .bdrv_co_check = vmdk_co_check,
417
.bdrv_reopen_prepare = vmdk_reopen_prepare,
418
.bdrv_child_perm = bdrv_format_default_perms,
419
.bdrv_co_preadv = vmdk_co_preadv,
420
--
37
--
421
2.13.6
38
2.19.1
422
39
423
40
diff view generated by jsdifflib
Deleted patch
1
This creates a BlockdevCreateOptions union type that will contain all of
2
the options for image creation. We'll start out with an empty struct
3
type BlockdevCreateNotSupported for all drivers.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
---
9
qapi/block-core.json | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 62 insertions(+)
11
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
17
{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
18
19
##
20
+# @BlockdevCreateNotSupported:
21
+#
22
+# This is used for all drivers that don't support creating images.
23
+#
24
+# Since: 2.12
25
+##
26
+{ 'struct': 'BlockdevCreateNotSupported', 'data': {}}
27
+
28
+##
29
+# @BlockdevCreateOptions:
30
+#
31
+# Options for creating an image format on a given node.
32
+#
33
+# @driver block driver to create the image format
34
+#
35
+# Since: 2.12
36
+##
37
+{ 'union': 'BlockdevCreateOptions',
38
+ 'base': {
39
+ 'driver': 'BlockdevDriver' },
40
+ 'discriminator': 'driver',
41
+ 'data': {
42
+ 'blkdebug': 'BlockdevCreateNotSupported',
43
+ 'blkverify': 'BlockdevCreateNotSupported',
44
+ 'bochs': 'BlockdevCreateNotSupported',
45
+ 'cloop': 'BlockdevCreateNotSupported',
46
+ 'dmg': 'BlockdevCreateNotSupported',
47
+ 'file': 'BlockdevCreateNotSupported',
48
+ 'ftp': 'BlockdevCreateNotSupported',
49
+ 'ftps': 'BlockdevCreateNotSupported',
50
+ 'gluster': 'BlockdevCreateNotSupported',
51
+ 'host_cdrom': 'BlockdevCreateNotSupported',
52
+ 'host_device': 'BlockdevCreateNotSupported',
53
+ 'http': 'BlockdevCreateNotSupported',
54
+ 'https': 'BlockdevCreateNotSupported',
55
+ 'iscsi': 'BlockdevCreateNotSupported',
56
+ 'luks': 'BlockdevCreateNotSupported',
57
+ 'nbd': 'BlockdevCreateNotSupported',
58
+ 'nfs': 'BlockdevCreateNotSupported',
59
+ 'null-aio': 'BlockdevCreateNotSupported',
60
+ 'null-co': 'BlockdevCreateNotSupported',
61
+ 'nvme': 'BlockdevCreateNotSupported',
62
+ 'parallels': 'BlockdevCreateNotSupported',
63
+ 'qcow2': 'BlockdevCreateNotSupported',
64
+ 'qcow': 'BlockdevCreateNotSupported',
65
+ 'qed': 'BlockdevCreateNotSupported',
66
+ 'quorum': 'BlockdevCreateNotSupported',
67
+ 'raw': 'BlockdevCreateNotSupported',
68
+ 'rbd': 'BlockdevCreateNotSupported',
69
+ 'replication': 'BlockdevCreateNotSupported',
70
+ 'sheepdog': 'BlockdevCreateNotSupported',
71
+ 'ssh': 'BlockdevCreateNotSupported',
72
+ 'throttle': 'BlockdevCreateNotSupported',
73
+ 'vdi': 'BlockdevCreateNotSupported',
74
+ 'vhdx': 'BlockdevCreateNotSupported',
75
+ 'vmdk': 'BlockdevCreateNotSupported',
76
+ 'vpc': 'BlockdevCreateNotSupported',
77
+ 'vvfat': 'BlockdevCreateNotSupported',
78
+ 'vxhs': 'BlockdevCreateNotSupported'
79
+ } }
80
+
81
+##
82
# @blockdev-open-tray:
83
#
84
# Opens a block device's tray. If there is a block driver state tree inserted as
85
--
86
2.13.6
87
88
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
---
5
qapi/block-core.json | 45 ++++++++++++++++++++++++++++++++++++++++++++-
6
1 file changed, 44 insertions(+), 1 deletion(-)
7
1
8
diff --git a/qapi/block-core.json b/qapi/block-core.json
9
index XXXXXXX..XXXXXXX 100644
10
--- a/qapi/block-core.json
11
+++ b/qapi/block-core.json
12
@@ -XXX,XX +XXX,XX @@
13
{ 'command': 'blockdev-del', 'data': { 'node-name': 'str' } }
14
15
##
16
+# @BlockdevQcow2Version:
17
+#
18
+# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2)
19
+# @v3: The extended QCOW2 format as introduced in qemu 1.1 (version 3)
20
+#
21
+# Since: 2.12
22
+##
23
+{ 'enum': 'BlockdevQcow2Version',
24
+ 'data': [ 'v2', 'v3' ] }
25
+
26
+
27
+##
28
+# @BlockdevCreateOptionsQcow2:
29
+#
30
+# Driver specific image creation options for qcow2.
31
+#
32
+# @file Node to create the image format on
33
+# @size Size of the virtual disk in bytes
34
+# @version Compatibility level (default: v3)
35
+# @backing-file File name of the backing file if a backing file
36
+# should be used
37
+# @backing-fmt Name of the block driver to use for the backing file
38
+# @encrypt Encryption options if the image should be encrypted
39
+# @cluster-size qcow2 cluster size in bytes (default: 65536)
40
+# @preallocation Preallocation mode for the new image (default: off)
41
+# @lazy-refcounts True if refcounts may be updated lazily (default: off)
42
+# @refcount-bits Width of reference counts in bits (default: 16)
43
+#
44
+# Since: 2.12
45
+##
46
+{ 'struct': 'BlockdevCreateOptionsQcow2',
47
+ 'data': { 'file': 'BlockdevRef',
48
+ 'size': 'size',
49
+ '*version': 'BlockdevQcow2Version',
50
+ '*backing-file': 'str',
51
+ '*backing-fmt': 'BlockdevDriver',
52
+ '*encrypt': 'QCryptoBlockCreateOptions',
53
+ '*cluster-size': 'size',
54
+ '*preallocation': 'PreallocMode',
55
+ '*lazy-refcounts': 'bool',
56
+ '*refcount-bits': 'int' } }
57
+
58
+##
59
# @BlockdevCreateNotSupported:
60
#
61
# This is used for all drivers that don't support creating images.
62
@@ -XXX,XX +XXX,XX @@
63
'null-co': 'BlockdevCreateNotSupported',
64
'nvme': 'BlockdevCreateNotSupported',
65
'parallels': 'BlockdevCreateNotSupported',
66
- 'qcow2': 'BlockdevCreateNotSupported',
67
+ 'qcow2': 'BlockdevCreateOptionsQcow2',
68
'qcow': 'BlockdevCreateNotSupported',
69
'qed': 'BlockdevCreateNotSupported',
70
'quorum': 'BlockdevCreateNotSupported',
71
--
72
2.13.6
73
74
diff view generated by jsdifflib
Deleted patch
1
The functions originally known as qcow2_create() and qcow2_create2()
2
are now called qcow2_co_create_opts() and qcow2_co_create(), which
3
matches the names of the BlockDriver callbacks that they will implement
4
at the end of this patch series.
5
1
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/qcow2.c | 16 ++++++++--------
11
1 file changed, 8 insertions(+), 8 deletions(-)
12
13
diff --git a/block/qcow2.c b/block/qcow2.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2.c
16
+++ b/block/qcow2.c
17
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
18
}
19
20
static int coroutine_fn
21
-qcow2_co_create2(const char *filename, int64_t total_size,
22
- const char *backing_file, const char *backing_format,
23
- int flags, size_t cluster_size, PreallocMode prealloc,
24
- QemuOpts *opts, int version, int refcount_order,
25
- const char *encryptfmt, Error **errp)
26
+qcow2_co_create(const char *filename, int64_t total_size,
27
+ const char *backing_file, const char *backing_format,
28
+ int flags, size_t cluster_size, PreallocMode prealloc,
29
+ QemuOpts *opts, int version, int refcount_order,
30
+ const char *encryptfmt, Error **errp)
31
{
32
QDict *options;
33
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
35
36
refcount_order = ctz32(refcount_bits);
37
38
- ret = qcow2_co_create2(filename, size, backing_file, backing_fmt, flags,
39
- cluster_size, prealloc, opts, version, refcount_order,
40
- encryptfmt, &local_err);
41
+ ret = qcow2_co_create(filename, size, backing_file, backing_fmt, flags,
42
+ cluster_size, prealloc, opts, version, refcount_order,
43
+ encryptfmt, &local_err);
44
error_propagate(errp, local_err);
45
46
finish:
47
--
48
2.13.6
49
50
diff view generated by jsdifflib
Deleted patch
1
Currently, qcow2_create() only parses the QemuOpts and then calls
2
qcow2_co_create() for the actual image creation, which includes both the
3
creation of the actual file on the file system and writing a valid empty
4
qcow2 image into that file.
5
1
6
The plan is that qcow2_co_create() becomes the function that implements
7
the functionality for a future 'blockdev-create' QMP command, which only
8
creates the qcow2 layer on an already opened file node.
9
10
This is a first step towards that goal: Let's move out anything that
11
deals with the protocol layer from qcow2_co_create() into
12
qcow2_create(). This means that qcow2_co_create() doesn't need a file
13
name any more.
14
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2.c | 64 +++++++++++++++++++++++++++++++++++------------------------
20
1 file changed, 38 insertions(+), 26 deletions(-)
21
22
diff --git a/block/qcow2.c b/block/qcow2.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2.c
25
+++ b/block/qcow2.c
26
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
27
}
28
29
static int coroutine_fn
30
-qcow2_co_create(const char *filename, int64_t total_size,
31
+qcow2_co_create(BlockDriverState *bs, int64_t total_size,
32
const char *backing_file, const char *backing_format,
33
int flags, size_t cluster_size, PreallocMode prealloc,
34
QemuOpts *opts, int version, int refcount_order,
35
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(const char *filename, int64_t total_size,
36
Error *local_err = NULL;
37
int ret;
38
39
- if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
40
- int64_t prealloc_size =
41
- qcow2_calc_prealloc_size(total_size, cluster_size, refcount_order);
42
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
43
- qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_str(prealloc),
44
- &error_abort);
45
- }
46
-
47
- ret = bdrv_create_file(filename, opts, &local_err);
48
+ blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
49
+ ret = blk_insert_bs(blk, bs, errp);
50
if (ret < 0) {
51
- error_propagate(errp, local_err);
52
- return ret;
53
- }
54
-
55
- blk = blk_new_open(filename, NULL, NULL,
56
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL,
57
- &local_err);
58
- if (blk == NULL) {
59
- error_propagate(errp, local_err);
60
- return -EIO;
61
+ goto out;
62
}
63
-
64
blk_set_allow_write_beyond_eof(blk, true);
65
66
/* Write the header */
67
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(const char *filename, int64_t total_size,
68
*/
69
options = qdict_new();
70
qdict_put_str(options, "driver", "qcow2");
71
- blk = blk_new_open(filename, NULL, options,
72
+ qdict_put_str(options, "file", bs->node_name);
73
+ blk = blk_new_open(NULL, NULL, options,
74
BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH,
75
&local_err);
76
if (blk == NULL) {
77
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(const char *filename, int64_t total_size,
78
*/
79
options = qdict_new();
80
qdict_put_str(options, "driver", "qcow2");
81
- blk = blk_new_open(filename, NULL, options,
82
+ qdict_put_str(options, "file", bs->node_name);
83
+ blk = blk_new_open(NULL, NULL, options,
84
BDRV_O_RDWR | BDRV_O_NO_BACKING | BDRV_O_NO_IO,
85
&local_err);
86
if (blk == NULL) {
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
88
uint64_t refcount_bits;
89
int refcount_order;
90
char *encryptfmt = NULL;
91
+ BlockDriverState *bs = NULL;
92
Error *local_err = NULL;
93
int ret;
94
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
96
97
refcount_order = ctz32(refcount_bits);
98
99
- ret = qcow2_co_create(filename, size, backing_file, backing_fmt, flags,
100
+ /* Create and open the file (protocol layer) */
101
+ if (prealloc == PREALLOC_MODE_FULL || prealloc == PREALLOC_MODE_FALLOC) {
102
+ int64_t prealloc_size =
103
+ qcow2_calc_prealloc_size(size, cluster_size, refcount_order);
104
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_abort);
105
+ qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_str(prealloc),
106
+ &error_abort);
107
+ }
108
+
109
+ ret = bdrv_create_file(filename, opts, errp);
110
+ if (ret < 0) {
111
+ goto finish;
112
+ }
113
+
114
+ bs = bdrv_open(filename, NULL, NULL,
115
+ BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
116
+ if (bs == NULL) {
117
+ ret = -EIO;
118
+ goto finish;
119
+ }
120
+
121
+ /* Create the qcow2 image (format layer) */
122
+ ret = qcow2_co_create(bs, size, backing_file, backing_fmt, flags,
123
cluster_size, prealloc, opts, version, refcount_order,
124
- encryptfmt, &local_err);
125
- error_propagate(errp, local_err);
126
+ encryptfmt, errp);
127
+ if (ret < 0) {
128
+ goto finish;
129
+ }
130
131
finish:
132
+ bdrv_unref(bs);
133
+
134
g_free(backing_file);
135
g_free(backing_fmt);
136
g_free(encryptfmt);
137
--
138
2.13.6
139
140
diff view generated by jsdifflib
Deleted patch
1
Instead of passing the encryption format name and the QemuOpts down, use
2
the QCryptoBlockCreateOptions contained in BlockdevCreateOptions.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/qcow2.c | 62 +++++++++++++++++++++++++++++++++++++++++++----------------
9
1 file changed, 45 insertions(+), 17 deletions(-)
10
11
diff --git a/block/qcow2.c b/block/qcow2.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/qcow2.c
14
+++ b/block/qcow2.c
15
@@ -XXX,XX +XXX,XX @@ static int qcow2_crypt_method_from_format(const char *encryptfmt)
16
}
17
}
18
19
-static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
20
- QemuOpts *opts, Error **errp)
21
+static QCryptoBlockCreateOptions *
22
+qcow2_parse_encryption(const char *encryptfmt, QemuOpts *opts, Error **errp)
23
{
24
- BDRVQcow2State *s = bs->opaque;
25
QCryptoBlockCreateOptions *cryptoopts = NULL;
26
- QCryptoBlock *crypto = NULL;
27
- int ret = -EINVAL;
28
QDict *options, *encryptopts;
29
int fmt;
30
31
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
32
error_setg(errp, "Unknown encryption format '%s'", encryptfmt);
33
break;
34
}
35
- if (!cryptoopts) {
36
- ret = -EINVAL;
37
- goto out;
38
+
39
+ QDECREF(encryptopts);
40
+ return cryptoopts;
41
+}
42
+
43
+static int qcow2_set_up_encryption(BlockDriverState *bs,
44
+ QCryptoBlockCreateOptions *cryptoopts,
45
+ Error **errp)
46
+{
47
+ BDRVQcow2State *s = bs->opaque;
48
+ QCryptoBlock *crypto = NULL;
49
+ int fmt, ret;
50
+
51
+ switch (cryptoopts->format) {
52
+ case Q_CRYPTO_BLOCK_FORMAT_LUKS:
53
+ fmt = QCOW_CRYPT_LUKS;
54
+ break;
55
+ case Q_CRYPTO_BLOCK_FORMAT_QCOW:
56
+ fmt = QCOW_CRYPT_AES;
57
+ break;
58
+ default:
59
+ error_setg(errp, "Crypto format not supported in qcow2");
60
+ return -EINVAL;
61
}
62
+
63
s->crypt_method_header = fmt;
64
65
crypto = qcrypto_block_create(cryptoopts, "encrypt.",
66
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
67
qcow2_crypto_hdr_write_func,
68
bs, errp);
69
if (!crypto) {
70
- ret = -EINVAL;
71
- goto out;
72
+ return -EINVAL;
73
}
74
75
ret = qcow2_update_header(bs);
76
@@ -XXX,XX +XXX,XX @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
77
goto out;
78
}
79
80
+ ret = 0;
81
out:
82
- QDECREF(encryptopts);
83
qcrypto_block_free(crypto);
84
- qapi_free_QCryptoBlockCreateOptions(cryptoopts);
85
return ret;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int version,
89
}
90
91
static int coroutine_fn
92
-qcow2_co_create(BlockdevCreateOptions *create_options, QemuOpts *opts,
93
- const char *encryptfmt, Error **errp)
94
+qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
95
{
96
BlockdevCreateOptionsQcow2 *qcow2_opts;
97
QDict *options;
98
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, QemuOpts *opts,
99
}
100
101
/* Want encryption? There you go. */
102
- if (encryptfmt) {
103
- ret = qcow2_set_up_encryption(blk_bs(blk), encryptfmt, opts, errp);
104
+ if (qcow2_opts->has_encrypt) {
105
+ ret = qcow2_set_up_encryption(blk_bs(blk), qcow2_opts->encrypt, errp);
106
if (ret < 0) {
107
goto out;
108
}
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
110
int version;
111
uint64_t refcount_bits;
112
char *encryptfmt = NULL;
113
+ QCryptoBlockCreateOptions *cryptoopts = NULL;
114
BlockDriverState *bs = NULL;
115
Error *local_err = NULL;
116
int ret;
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
118
ret = -EINVAL;
119
goto finish;
120
}
121
+
122
encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
123
if (encryptfmt) {
124
if (qemu_opt_get(opts, BLOCK_OPT_ENCRYPT)) {
125
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
126
} else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
127
encryptfmt = g_strdup("aes");
128
}
129
+ if (encryptfmt) {
130
+ cryptoopts = qcow2_parse_encryption(encryptfmt, opts, errp);
131
+ if (cryptoopts == NULL) {
132
+ ret = -EINVAL;
133
+ goto finish;
134
+ }
135
+ }
136
+
137
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
138
if (local_err) {
139
error_propagate(errp, local_err);
140
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
141
.backing_file = backing_file,
142
.has_backing_fmt = (backing_fmt != NULL),
143
.backing_fmt = backing_drv,
144
+ .has_encrypt = (encryptfmt != NULL),
145
+ .encrypt = cryptoopts,
146
.has_cluster_size = true,
147
.cluster_size = cluster_size,
148
.has_preallocation = true,
149
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
150
.refcount_bits = refcount_bits,
151
},
152
};
153
- ret = qcow2_co_create(&create_options, opts, encryptfmt, errp);
154
+ ret = qcow2_co_create(&create_options, errp);
155
if (ret < 0) {
156
goto finish;
157
}
158
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opt
159
finish:
160
bdrv_unref(bs);
161
162
+ qapi_free_QCryptoBlockCreateOptions(cryptoopts);
163
g_free(backing_file);
164
g_free(backing_fmt);
165
g_free(encryptfmt);
166
--
167
2.13.6
168
169
diff view generated by jsdifflib
Deleted patch
1
Basic test for merging two QemuOptsLists.
2
1
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
tests/test-qemu-opts.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++
8
1 file changed, 128 insertions(+)
9
10
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/test-qemu-opts.c
13
+++ b/tests/test-qemu-opts.c
14
@@ -XXX,XX +XXX,XX @@ static QemuOptsList opts_list_01 = {
15
{
16
.name = "str1",
17
.type = QEMU_OPT_STRING,
18
+ .help = "Help texts are preserved in qemu_opts_append",
19
+ .def_value_str = "default",
20
},{
21
.name = "str2",
22
.type = QEMU_OPT_STRING,
23
@@ -XXX,XX +XXX,XX @@ static QemuOptsList opts_list_01 = {
24
},{
25
.name = "number1",
26
.type = QEMU_OPT_NUMBER,
27
+ .help = "Having help texts only for some options is okay",
28
},{
29
.name = "number2",
30
.type = QEMU_OPT_NUMBER,
31
@@ -XXX,XX +XXX,XX @@ static void test_opts_parse_size(void)
32
qemu_opts_reset(&opts_list_02);
33
}
34
35
+static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
36
+{
37
+ int i = 0;
38
+
39
+ if (with_overlapping) {
40
+ g_assert_cmpstr(desc[i].name, ==, "str1");
41
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
42
+ g_assert_cmpstr(desc[i].help, ==,
43
+ "Help texts are preserved in qemu_opts_append");
44
+ g_assert_cmpstr(desc[i].def_value_str, ==, "default");
45
+ i++;
46
+
47
+ g_assert_cmpstr(desc[i].name, ==, "str2");
48
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
49
+ g_assert_cmpstr(desc[i].help, ==, NULL);
50
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
51
+ i++;
52
+ }
53
+
54
+ g_assert_cmpstr(desc[i].name, ==, "str3");
55
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
56
+ g_assert_cmpstr(desc[i].help, ==, NULL);
57
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
58
+ i++;
59
+
60
+ g_assert_cmpstr(desc[i].name, ==, "number1");
61
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
62
+ g_assert_cmpstr(desc[i].help, ==,
63
+ "Having help texts only for some options is okay");
64
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
65
+ i++;
66
+
67
+ g_assert_cmpstr(desc[i].name, ==, "number2");
68
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
69
+ g_assert_cmpstr(desc[i].help, ==, NULL);
70
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
71
+ i++;
72
+
73
+ g_assert_cmpstr(desc[i].name, ==, NULL);
74
+}
75
+
76
+static void append_verify_list_02(QemuOptDesc *desc)
77
+{
78
+ int i = 0;
79
+
80
+ g_assert_cmpstr(desc[i].name, ==, "str1");
81
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
82
+ g_assert_cmpstr(desc[i].help, ==, NULL);
83
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
84
+ i++;
85
+
86
+ g_assert_cmpstr(desc[i].name, ==, "str2");
87
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
88
+ g_assert_cmpstr(desc[i].help, ==, NULL);
89
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
90
+ i++;
91
+
92
+ g_assert_cmpstr(desc[i].name, ==, "bool1");
93
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
94
+ g_assert_cmpstr(desc[i].help, ==, NULL);
95
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
96
+ i++;
97
+
98
+ g_assert_cmpstr(desc[i].name, ==, "bool2");
99
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
100
+ g_assert_cmpstr(desc[i].help, ==, NULL);
101
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
102
+ i++;
103
+
104
+ g_assert_cmpstr(desc[i].name, ==, "size1");
105
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
106
+ g_assert_cmpstr(desc[i].help, ==, NULL);
107
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
108
+ i++;
109
+
110
+ g_assert_cmpstr(desc[i].name, ==, "size2");
111
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
112
+ g_assert_cmpstr(desc[i].help, ==, NULL);
113
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
114
+ i++;
115
+
116
+ g_assert_cmpstr(desc[i].name, ==, "size3");
117
+ g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
118
+ g_assert_cmpstr(desc[i].help, ==, NULL);
119
+ g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
120
+}
121
+
122
+static void test_opts_append_to_null(void)
123
+{
124
+ QemuOptsList *merged;
125
+
126
+ merged = qemu_opts_append(NULL, &opts_list_01);
127
+ g_assert(merged != &opts_list_01);
128
+
129
+ g_assert_cmpstr(merged->name, ==, NULL);
130
+ g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
131
+ g_assert_false(merged->merge_lists);
132
+
133
+ append_verify_list_01(merged->desc, true);
134
+
135
+ qemu_opts_free(merged);
136
+}
137
+
138
+static void test_opts_append(void)
139
+{
140
+ QemuOptsList *first, *merged;
141
+
142
+ first = qemu_opts_append(NULL, &opts_list_02);
143
+ merged = qemu_opts_append(first, &opts_list_01);
144
+ g_assert(first != &opts_list_02);
145
+ g_assert(merged != &opts_list_01);
146
+
147
+ g_assert_cmpstr(merged->name, ==, NULL);
148
+ g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
149
+ g_assert_false(merged->merge_lists);
150
+
151
+ append_verify_list_02(&merged->desc[0]);
152
+ append_verify_list_01(&merged->desc[7], false);
153
+
154
+ qemu_opts_free(merged);
155
+}
156
+
157
+
158
int main(int argc, char *argv[])
159
{
160
register_opts();
161
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
162
g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
163
g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
164
g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
165
+ g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
166
+ g_test_add_func("/qemu-opts/append", test_opts_append);
167
g_test_run();
168
return 0;
169
}
170
--
171
2.13.6
172
173
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Reviewed-by: Eric Blake <eblake@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
---
5
tests/test-qemu-opts.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++
6
1 file changed, 125 insertions(+)
7
1
8
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/tests/test-qemu-opts.c
11
+++ b/tests/test-qemu-opts.c
12
@@ -XXX,XX +XXX,XX @@
13
#include "qemu/osdep.h"
14
#include "qemu/cutils.h"
15
#include "qemu/option.h"
16
+#include "qemu/option_int.h"
17
#include "qapi/error.h"
18
#include "qapi/qmp/qdict.h"
19
#include "qapi/qmp/qstring.h"
20
@@ -XXX,XX +XXX,XX @@ static void test_opts_append(void)
21
qemu_opts_free(merged);
22
}
23
24
+static void test_opts_to_qdict_basic(void)
25
+{
26
+ QemuOpts *opts;
27
+ QDict *dict;
28
+
29
+ opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42",
30
+ false, &error_abort);
31
+ g_assert(opts != NULL);
32
+
33
+ dict = qemu_opts_to_qdict(opts, NULL);
34
+ g_assert(dict != NULL);
35
+
36
+ g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
37
+ g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
38
+ g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
39
+ g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
40
+ g_assert_false(qdict_haskey(dict, "number2"));
41
+
42
+ QDECREF(dict);
43
+ qemu_opts_del(opts);
44
+}
45
+
46
+static void test_opts_to_qdict_filtered(void)
47
+{
48
+ QemuOptsList *first, *merged;
49
+ QemuOpts *opts;
50
+ QDict *dict;
51
+
52
+ first = qemu_opts_append(NULL, &opts_list_02);
53
+ merged = qemu_opts_append(first, &opts_list_01);
54
+
55
+ opts = qemu_opts_parse(merged,
56
+ "str1=foo,str2=,str3=bar,bool1=off,number1=42",
57
+ false, &error_abort);
58
+ g_assert(opts != NULL);
59
+
60
+ /* Convert to QDict without deleting from opts */
61
+ dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false);
62
+ g_assert(dict != NULL);
63
+ g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
64
+ g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
65
+ g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
66
+ g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
67
+ g_assert_false(qdict_haskey(dict, "number2"));
68
+ g_assert_false(qdict_haskey(dict, "bool1"));
69
+ QDECREF(dict);
70
+
71
+ dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false);
72
+ g_assert(dict != NULL);
73
+ g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
74
+ g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
75
+ g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
76
+ g_assert_false(qdict_haskey(dict, "str3"));
77
+ g_assert_false(qdict_haskey(dict, "number1"));
78
+ g_assert_false(qdict_haskey(dict, "number2"));
79
+ QDECREF(dict);
80
+
81
+ /* Now delete converted options from opts */
82
+ dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true);
83
+ g_assert(dict != NULL);
84
+ g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
85
+ g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
86
+ g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
87
+ g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
88
+ g_assert_false(qdict_haskey(dict, "number2"));
89
+ g_assert_false(qdict_haskey(dict, "bool1"));
90
+ QDECREF(dict);
91
+
92
+ dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true);
93
+ g_assert(dict != NULL);
94
+ g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
95
+ g_assert_false(qdict_haskey(dict, "str1"));
96
+ g_assert_false(qdict_haskey(dict, "str2"));
97
+ g_assert_false(qdict_haskey(dict, "str3"));
98
+ g_assert_false(qdict_haskey(dict, "number1"));
99
+ g_assert_false(qdict_haskey(dict, "number2"));
100
+ QDECREF(dict);
101
+
102
+ g_assert_true(QTAILQ_EMPTY(&opts->head));
103
+
104
+ qemu_opts_del(opts);
105
+ qemu_opts_free(merged);
106
+}
107
+
108
+static void test_opts_to_qdict_duplicates(void)
109
+{
110
+ QemuOpts *opts;
111
+ QemuOpt *opt;
112
+ QDict *dict;
113
+
114
+ opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort);
115
+ g_assert(opts != NULL);
116
+
117
+ /* Verify that opts has two options with the same name */
118
+ opt = QTAILQ_FIRST(&opts->head);
119
+ g_assert_cmpstr(opt->name, ==, "foo");
120
+ g_assert_cmpstr(opt->str , ==, "a");
121
+
122
+ opt = QTAILQ_NEXT(opt, next);
123
+ g_assert_cmpstr(opt->name, ==, "foo");
124
+ g_assert_cmpstr(opt->str , ==, "b");
125
+
126
+ opt = QTAILQ_NEXT(opt, next);
127
+ g_assert(opt == NULL);
128
+
129
+ /* In the conversion to QDict, the last one wins */
130
+ dict = qemu_opts_to_qdict(opts, NULL);
131
+ g_assert(dict != NULL);
132
+ g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
133
+ QDECREF(dict);
134
+
135
+ /* The last one still wins if entries are deleted, and both are deleted */
136
+ dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true);
137
+ g_assert(dict != NULL);
138
+ g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
139
+ QDECREF(dict);
140
+
141
+ g_assert_true(QTAILQ_EMPTY(&opts->head));
142
+
143
+ qemu_opts_del(opts);
144
+}
145
146
int main(int argc, char *argv[])
147
{
148
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
149
g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
150
g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
151
g_test_add_func("/qemu-opts/append", test_opts_append);
152
+ g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
153
+ g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered);
154
+ g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates);
155
g_test_run();
156
return 0;
157
}
158
--
159
2.13.6
160
161
diff view generated by jsdifflib
Deleted patch
1
A few block drivers will need to rename .bdrv_create options for their
2
QAPIfication, so let's have a helper function for that.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
---
8
include/qapi/qmp/qdict.h | 6 +++
9
qobject/qdict.c | 34 +++++++++++++
10
tests/check-qdict.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 169 insertions(+)
12
13
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/qapi/qmp/qdict.h
16
+++ b/include/qapi/qmp/qdict.h
17
@@ -XXX,XX +XXX,XX @@ QObject *qdict_crumple(const QDict *src, Error **errp);
18
19
void qdict_join(QDict *dest, QDict *src, bool overwrite);
20
21
+typedef struct QDictRenames {
22
+ const char *from;
23
+ const char *to;
24
+} QDictRenames;
25
+bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp);
26
+
27
#endif /* QDICT_H */
28
diff --git a/qobject/qdict.c b/qobject/qdict.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/qobject/qdict.c
31
+++ b/qobject/qdict.c
32
@@ -XXX,XX +XXX,XX @@ void qdict_join(QDict *dest, QDict *src, bool overwrite)
33
entry = next;
34
}
35
}
36
+
37
+/**
38
+ * qdict_rename_keys(): Rename keys in qdict according to the replacements
39
+ * specified in the array renames. The array must be terminated by an entry
40
+ * with from = NULL.
41
+ *
42
+ * The renames are performed individually in the order of the array, so entries
43
+ * may be renamed multiple times and may or may not conflict depending on the
44
+ * order of the renames array.
45
+ *
46
+ * Returns true for success, false in error cases.
47
+ */
48
+bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **errp)
49
+{
50
+ QObject *qobj;
51
+
52
+ while (renames->from) {
53
+ if (qdict_haskey(qdict, renames->from)) {
54
+ if (qdict_haskey(qdict, renames->to)) {
55
+ error_setg(errp, "'%s' and its alias '%s' can't be used at the "
56
+ "same time", renames->to, renames->from);
57
+ return false;
58
+ }
59
+
60
+ qobj = qdict_get(qdict, renames->from);
61
+ qobject_incref(qobj);
62
+ qdict_put_obj(qdict, renames->to, qobj);
63
+ qdict_del(qdict, renames->from);
64
+ }
65
+
66
+ renames++;
67
+ }
68
+ return true;
69
+}
70
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tests/check-qdict.c
73
+++ b/tests/check-qdict.c
74
@@ -XXX,XX +XXX,XX @@ static void qdict_crumple_test_empty(void)
75
QDECREF(dst);
76
}
77
78
+static int qdict_count_entries(QDict *dict)
79
+{
80
+ const QDictEntry *e;
81
+ int count = 0;
82
+
83
+ for (e = qdict_first(dict); e; e = qdict_next(dict, e)) {
84
+ count++;
85
+ }
86
+
87
+ return count;
88
+}
89
+
90
+static void qdict_rename_keys_test(void)
91
+{
92
+ QDict *dict = qdict_new();
93
+ QDict *copy;
94
+ QDictRenames *renames;
95
+ Error *local_err = NULL;
96
+
97
+ qdict_put_str(dict, "abc", "foo");
98
+ qdict_put_str(dict, "abcdef", "bar");
99
+ qdict_put_int(dict, "number", 42);
100
+ qdict_put_bool(dict, "flag", true);
101
+ qdict_put_null(dict, "nothing");
102
+
103
+ /* Empty rename list */
104
+ renames = (QDictRenames[]) {
105
+ { NULL, "this can be anything" }
106
+ };
107
+ copy = qdict_clone_shallow(dict);
108
+ qdict_rename_keys(copy, renames, &error_abort);
109
+
110
+ g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "foo");
111
+ g_assert_cmpstr(qdict_get_str(copy, "abcdef"), ==, "bar");
112
+ g_assert_cmpint(qdict_get_int(copy, "number"), ==, 42);
113
+ g_assert_cmpint(qdict_get_bool(copy, "flag"), ==, true);
114
+ g_assert(qobject_type(qdict_get(copy, "nothing")) == QTYPE_QNULL);
115
+ g_assert_cmpint(qdict_count_entries(copy), ==, 5);
116
+
117
+ QDECREF(copy);
118
+
119
+ /* Simple rename of all entries */
120
+ renames = (QDictRenames[]) {
121
+ { "abc", "str1" },
122
+ { "abcdef", "str2" },
123
+ { "number", "int" },
124
+ { "flag", "bool" },
125
+ { "nothing", "null" },
126
+ { NULL , NULL }
127
+ };
128
+ copy = qdict_clone_shallow(dict);
129
+ qdict_rename_keys(copy, renames, &error_abort);
130
+
131
+ g_assert(!qdict_haskey(copy, "abc"));
132
+ g_assert(!qdict_haskey(copy, "abcdef"));
133
+ g_assert(!qdict_haskey(copy, "number"));
134
+ g_assert(!qdict_haskey(copy, "flag"));
135
+ g_assert(!qdict_haskey(copy, "nothing"));
136
+
137
+ g_assert_cmpstr(qdict_get_str(copy, "str1"), ==, "foo");
138
+ g_assert_cmpstr(qdict_get_str(copy, "str2"), ==, "bar");
139
+ g_assert_cmpint(qdict_get_int(copy, "int"), ==, 42);
140
+ g_assert_cmpint(qdict_get_bool(copy, "bool"), ==, true);
141
+ g_assert(qobject_type(qdict_get(copy, "null")) == QTYPE_QNULL);
142
+ g_assert_cmpint(qdict_count_entries(copy), ==, 5);
143
+
144
+ QDECREF(copy);
145
+
146
+ /* Renames are processed top to bottom */
147
+ renames = (QDictRenames[]) {
148
+ { "abc", "tmp" },
149
+ { "abcdef", "abc" },
150
+ { "number", "abcdef" },
151
+ { "flag", "number" },
152
+ { "nothing", "flag" },
153
+ { "tmp", "nothing" },
154
+ { NULL , NULL }
155
+ };
156
+ copy = qdict_clone_shallow(dict);
157
+ qdict_rename_keys(copy, renames, &error_abort);
158
+
159
+ g_assert_cmpstr(qdict_get_str(copy, "nothing"), ==, "foo");
160
+ g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "bar");
161
+ g_assert_cmpint(qdict_get_int(copy, "abcdef"), ==, 42);
162
+ g_assert_cmpint(qdict_get_bool(copy, "number"), ==, true);
163
+ g_assert(qobject_type(qdict_get(copy, "flag")) == QTYPE_QNULL);
164
+ g_assert(!qdict_haskey(copy, "tmp"));
165
+ g_assert_cmpint(qdict_count_entries(copy), ==, 5);
166
+
167
+ QDECREF(copy);
168
+
169
+ /* Conflicting rename */
170
+ renames = (QDictRenames[]) {
171
+ { "abcdef", "abc" },
172
+ { NULL , NULL }
173
+ };
174
+ copy = qdict_clone_shallow(dict);
175
+ qdict_rename_keys(copy, renames, &local_err);
176
+
177
+ g_assert(local_err != NULL);
178
+ error_free(local_err);
179
+ local_err = NULL;
180
+
181
+ g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "foo");
182
+ g_assert_cmpstr(qdict_get_str(copy, "abcdef"), ==, "bar");
183
+ g_assert_cmpint(qdict_get_int(copy, "number"), ==, 42);
184
+ g_assert_cmpint(qdict_get_bool(copy, "flag"), ==, true);
185
+ g_assert(qobject_type(qdict_get(copy, "nothing")) == QTYPE_QNULL);
186
+ g_assert_cmpint(qdict_count_entries(copy), ==, 5);
187
+
188
+ QDECREF(copy);
189
+
190
+ /* Renames in an empty dict */
191
+ renames = (QDictRenames[]) {
192
+ { "abcdef", "abc" },
193
+ { NULL , NULL }
194
+ };
195
+
196
+ QDECREF(dict);
197
+ dict = qdict_new();
198
+
199
+ qdict_rename_keys(dict, renames, &error_abort);
200
+ g_assert(qdict_first(dict) == NULL);
201
+
202
+ QDECREF(dict);
203
+}
204
+
205
static void qdict_crumple_test_bad_inputs(void)
206
{
207
QDict *src;
208
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
209
g_test_add_func("/public/crumple/bad_inputs",
210
qdict_crumple_test_bad_inputs);
211
212
+ g_test_add_func("/public/rename_keys", qdict_rename_keys_test);
213
+
214
/* The Big one */
215
if (g_test_slow()) {
216
g_test_add_func("/stress/test", qdict_stress_test);
217
--
218
2.13.6
219
220
diff view generated by jsdifflib
Deleted patch
1
Instead of manually creating the BlockdevCreateOptions object, use a
2
visitor to parse the given options into the QAPI object.
3
1
4
This involves translation from the old command line syntax to the syntax
5
mandated by the QAPI schema. Option names are still checked against
6
qcow2_create_opts, so only the old option names are allowed on the
7
command line, even if they are translated in qcow2_create().
8
9
In contrast, new option values are optionally recognised besides the old
10
values: 'compat' accepts 'v2'/'v3' as an alias for '0.10'/'1.1', and
11
'encrypt.format' accepts 'qcow' as an alias for 'aes' now.
12
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
---
17
block/qcow2.c | 218 ++++++++++++++++-----------------------------
18
tests/qemu-iotests/049.out | 8 +-
19
tests/qemu-iotests/112.out | 4 +-
20
3 files changed, 84 insertions(+), 146 deletions(-)
21
22
diff --git a/block/qcow2.c b/block/qcow2.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2.c
25
+++ b/block/qcow2.c
26
@@ -XXX,XX +XXX,XX @@
27
#include "qemu/option_int.h"
28
#include "qemu/cutils.h"
29
#include "qemu/bswap.h"
30
-#include "qapi/opts-visitor.h"
31
+#include "qapi/qobject-input-visitor.h"
32
+#include "qapi/qapi-visit-block-core.h"
33
#include "block/crypto.h"
34
35
/*
36
@@ -XXX,XX +XXX,XX @@ static int qcow2_crypt_method_from_format(const char *encryptfmt)
37
}
38
}
39
40
-static QCryptoBlockCreateOptions *
41
-qcow2_parse_encryption(const char *encryptfmt, QemuOpts *opts, Error **errp)
42
-{
43
- QCryptoBlockCreateOptions *cryptoopts = NULL;
44
- QDict *options, *encryptopts;
45
- int fmt;
46
-
47
- options = qemu_opts_to_qdict(opts, NULL);
48
- qdict_extract_subqdict(options, &encryptopts, "encrypt.");
49
- QDECREF(options);
50
-
51
- fmt = qcow2_crypt_method_from_format(encryptfmt);
52
-
53
- switch (fmt) {
54
- case QCOW_CRYPT_LUKS:
55
- cryptoopts = block_crypto_create_opts_init(
56
- Q_CRYPTO_BLOCK_FORMAT_LUKS, encryptopts, errp);
57
- break;
58
- case QCOW_CRYPT_AES:
59
- cryptoopts = block_crypto_create_opts_init(
60
- Q_CRYPTO_BLOCK_FORMAT_QCOW, encryptopts, errp);
61
- break;
62
- default:
63
- error_setg(errp, "Unknown encryption format '%s'", encryptfmt);
64
- break;
65
- }
66
-
67
- QDECREF(encryptopts);
68
- return cryptoopts;
69
-}
70
-
71
static int qcow2_set_up_encryption(BlockDriverState *bs,
72
QCryptoBlockCreateOptions *cryptoopts,
73
Error **errp)
74
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
75
}
76
if (version < 3 && qcow2_opts->lazy_refcounts) {
77
error_setg(errp, "Lazy refcounts only supported with compatibility "
78
- "level 1.1 and above (use compat=1.1 or greater)");
79
+ "level 1.1 and above (use version=v3 or greater)");
80
ret = -EINVAL;
81
goto out;
82
}
83
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
84
}
85
if (version < 3 && qcow2_opts->refcount_bits != 16) {
86
error_setg(errp, "Different refcount widths than 16 bits require "
87
- "compatibility level 1.1 or above (use compat=1.1 or "
88
+ "compatibility level 1.1 or above (use version=v3 or "
89
"greater)");
90
ret = -EINVAL;
91
goto out;
92
@@ -XXX,XX +XXX,XX @@ out:
93
static int coroutine_fn qcow2_co_create_opts(const char *filename, QemuOpts *opts,
94
Error **errp)
95
{
96
- BlockdevCreateOptions create_options;
97
- char *backing_file = NULL;
98
- char *backing_fmt = NULL;
99
- BlockdevDriver backing_drv;
100
- char *buf = NULL;
101
- uint64_t size = 0;
102
- int flags = 0;
103
- size_t cluster_size = DEFAULT_CLUSTER_SIZE;
104
- PreallocMode prealloc;
105
- int version;
106
- uint64_t refcount_bits;
107
- char *encryptfmt = NULL;
108
- QCryptoBlockCreateOptions *cryptoopts = NULL;
109
+ BlockdevCreateOptions *create_options = NULL;
110
+ QDict *qdict = NULL;
111
+ QObject *qobj;
112
+ Visitor *v;
113
BlockDriverState *bs = NULL;
114
Error *local_err = NULL;
115
+ const char *val;
116
int ret;
117
118
- /* Read out options */
119
- size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
120
- BDRV_SECTOR_SIZE);
121
- backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
122
- backing_fmt = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FMT);
123
- backing_drv = qapi_enum_parse(&BlockdevDriver_lookup, backing_fmt,
124
- 0, &local_err);
125
- if (local_err) {
126
- error_propagate(errp, local_err);
127
+ /* Only the keyval visitor supports the dotted syntax needed for
128
+ * encryption, so go through a QDict before getting a QAPI type. Ignore
129
+ * options meant for the protocol layer so that the visitor doesn't
130
+ * complain. */
131
+ qdict = qemu_opts_to_qdict_filtered(opts, NULL, bdrv_qcow2.create_opts,
132
+ true);
133
+
134
+ /* Handle encryption options */
135
+ val = qdict_get_try_str(qdict, BLOCK_OPT_ENCRYPT);
136
+ if (val && !strcmp(val, "on")) {
137
+ qdict_put_str(qdict, BLOCK_OPT_ENCRYPT, "qcow");
138
+ } else if (val && !strcmp(val, "off")) {
139
+ qdict_del(qdict, BLOCK_OPT_ENCRYPT);
140
+ }
141
+
142
+ val = qdict_get_try_str(qdict, BLOCK_OPT_ENCRYPT_FORMAT);
143
+ if (val && !strcmp(val, "aes")) {
144
+ qdict_put_str(qdict, BLOCK_OPT_ENCRYPT_FORMAT, "qcow");
145
+ }
146
+
147
+ /* Convert compat=0.10/1.1 into compat=v2/v3, to be renamed into
148
+ * version=v2/v3 below. */
149
+ val = qdict_get_try_str(qdict, BLOCK_OPT_COMPAT_LEVEL);
150
+ if (val && !strcmp(val, "0.10")) {
151
+ qdict_put_str(qdict, BLOCK_OPT_COMPAT_LEVEL, "v2");
152
+ } else if (val && !strcmp(val, "1.1")) {
153
+ qdict_put_str(qdict, BLOCK_OPT_COMPAT_LEVEL, "v3");
154
+ }
155
+
156
+ /* Change legacy command line options into QMP ones */
157
+ static const QDictRenames opt_renames[] = {
158
+ { BLOCK_OPT_BACKING_FILE, "backing-file" },
159
+ { BLOCK_OPT_BACKING_FMT, "backing-fmt" },
160
+ { BLOCK_OPT_CLUSTER_SIZE, "cluster-size" },
161
+ { BLOCK_OPT_LAZY_REFCOUNTS, "lazy-refcounts" },
162
+ { BLOCK_OPT_REFCOUNT_BITS, "refcount-bits" },
163
+ { BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT },
164
+ { BLOCK_OPT_COMPAT_LEVEL, "version" },
165
+ { NULL, NULL },
166
+ };
167
+
168
+ if (!qdict_rename_keys(qdict, opt_renames, errp)) {
169
ret = -EINVAL;
170
goto finish;
171
}
172
173
- encryptfmt = qemu_opt_get_del(opts, BLOCK_OPT_ENCRYPT_FORMAT);
174
- if (encryptfmt) {
175
- if (qemu_opt_get(opts, BLOCK_OPT_ENCRYPT)) {
176
- error_setg(errp, "Options " BLOCK_OPT_ENCRYPT " and "
177
- BLOCK_OPT_ENCRYPT_FORMAT " are mutually exclusive");
178
- ret = -EINVAL;
179
- goto finish;
180
- }
181
- } else if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) {
182
- encryptfmt = g_strdup("aes");
183
- }
184
- if (encryptfmt) {
185
- cryptoopts = qcow2_parse_encryption(encryptfmt, opts, errp);
186
- if (cryptoopts == NULL) {
187
- ret = -EINVAL;
188
- goto finish;
189
- }
190
- }
191
-
192
- cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
193
- if (local_err) {
194
- error_propagate(errp, local_err);
195
- ret = -EINVAL;
196
+ /* Create and open the file (protocol layer) */
197
+ ret = bdrv_create_file(filename, opts, errp);
198
+ if (ret < 0) {
199
goto finish;
200
}
201
- buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
202
- prealloc = qapi_enum_parse(&PreallocMode_lookup, buf,
203
- PREALLOC_MODE_OFF, &local_err);
204
- if (local_err) {
205
- error_propagate(errp, local_err);
206
- ret = -EINVAL;
207
+
208
+ bs = bdrv_open(filename, NULL, NULL,
209
+ BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
210
+ if (bs == NULL) {
211
+ ret = -EIO;
212
goto finish;
213
}
214
215
- version = qcow2_opt_get_version_del(opts, &local_err);
216
- if (local_err) {
217
- error_propagate(errp, local_err);
218
+ /* Set 'driver' and 'node' options */
219
+ qdict_put_str(qdict, "driver", "qcow2");
220
+ qdict_put_str(qdict, "file", bs->node_name);
221
+
222
+ /* Now get the QAPI type BlockdevCreateOptions */
223
+ qobj = qdict_crumple(qdict, errp);
224
+ QDECREF(qdict);
225
+ qdict = qobject_to_qdict(qobj);
226
+ if (qdict == NULL) {
227
ret = -EINVAL;
228
goto finish;
229
}
230
231
- if (qemu_opt_get_bool_del(opts, BLOCK_OPT_LAZY_REFCOUNTS, false)) {
232
- flags |= BLOCK_FLAG_LAZY_REFCOUNTS;
233
- }
234
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
235
+ visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
236
+ visit_free(v);
237
238
- refcount_bits = qcow2_opt_get_refcount_bits_del(opts, version, &local_err);
239
if (local_err) {
240
error_propagate(errp, local_err);
241
ret = -EINVAL;
242
goto finish;
243
}
244
245
-
246
- /* Create and open the file (protocol layer) */
247
- ret = bdrv_create_file(filename, opts, errp);
248
- if (ret < 0) {
249
- goto finish;
250
- }
251
-
252
- bs = bdrv_open(filename, NULL, NULL,
253
- BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
254
- if (bs == NULL) {
255
- ret = -EIO;
256
- goto finish;
257
- }
258
+ /* Silently round up size */
259
+ create_options->u.qcow2.size = ROUND_UP(create_options->u.qcow2.size,
260
+ BDRV_SECTOR_SIZE);
261
262
/* Create the qcow2 image (format layer) */
263
- create_options = (BlockdevCreateOptions) {
264
- .driver = BLOCKDEV_DRIVER_QCOW2,
265
- .u.qcow2 = {
266
- .file = &(BlockdevRef) {
267
- .type = QTYPE_QSTRING,
268
- .u.reference = bs->node_name,
269
- },
270
- .size = size,
271
- .has_version = true,
272
- .version = version == 2
273
- ? BLOCKDEV_QCOW2_VERSION_V2
274
- : BLOCKDEV_QCOW2_VERSION_V3,
275
- .has_backing_file = (backing_file != NULL),
276
- .backing_file = backing_file,
277
- .has_backing_fmt = (backing_fmt != NULL),
278
- .backing_fmt = backing_drv,
279
- .has_encrypt = (encryptfmt != NULL),
280
- .encrypt = cryptoopts,
281
- .has_cluster_size = true,
282
- .cluster_size = cluster_size,
283
- .has_preallocation = true,
284
- .preallocation = prealloc,
285
- .has_lazy_refcounts = true,
286
- .lazy_refcounts = (flags & BLOCK_FLAG_LAZY_REFCOUNTS),
287
- .has_refcount_bits = true,
288
- .refcount_bits = refcount_bits,
289
- },
290
- };
291
- ret = qcow2_co_create(&create_options, errp);
292
+ ret = qcow2_co_create(create_options, errp);
293
if (ret < 0) {
294
goto finish;
295
}
296
297
+ ret = 0;
298
finish:
299
+ QDECREF(qdict);
300
bdrv_unref(bs);
301
-
302
- qapi_free_QCryptoBlockCreateOptions(cryptoopts);
303
- g_free(backing_file);
304
- g_free(backing_fmt);
305
- g_free(encryptfmt);
306
- g_free(buf);
307
+ qapi_free_BlockdevCreateOptions(create_options);
308
return ret;
309
}
310
311
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
312
index XXXXXXX..XXXXXXX 100644
313
--- a/tests/qemu-iotests/049.out
314
+++ b/tests/qemu-iotests/049.out
315
@@ -XXX,XX +XXX,XX @@ qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
316
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16
317
318
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
319
-qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42'
320
+qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
321
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16
322
323
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
324
-qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar'
325
+qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
326
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16
327
328
== Check preallocation option ==
329
@@ -XXX,XX +XXX,XX @@ qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
330
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16
331
332
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
333
-qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234
334
+qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
335
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16
336
337
== Check encryption option ==
338
@@ -XXX,XX +XXX,XX @@ qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
339
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16
340
341
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
342
-qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
343
+qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
344
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16
345
346
*** done
347
diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out
348
index XXXXXXX..XXXXXXX 100644
349
--- a/tests/qemu-iotests/112.out
350
+++ b/tests/qemu-iotests/112.out
351
@@ -XXX,XX +XXX,XX @@ refcount bits: 16
352
353
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
354
refcount bits: 16
355
-qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use or greater)
356
+qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
357
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
358
-qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use or greater)
359
+qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
360
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
361
362
=== Snapshot limit on refcount_bits=1 ===
363
--
364
2.13.6
365
366
diff view generated by jsdifflib
1
This adds a synchronous x-blockdev-create QMP command that can create
1
From: Leonid Bloch <lbloch@janustech.com>
2
qcow2 images on a given node name.
3
2
4
We don't want to block while creating an image, so this is not the final
3
The lookup table for power-of-two sizes was added in commit 540b8492618eb
5
interface in all aspects, but BlockdevCreateOptionsQcow2 and
4
for the purpose of having convenient shortcuts for these sizes in cases
6
.bdrv_co_create() are what they actually might look like in the end. In
5
when the literal number has to be present at compile time, and
7
any case, this should be good enough to test whether we interpret
6
expressions as '(1 * KiB)' can not be used. One such case is the
8
BlockdevCreateOptions as we should.
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.
9
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>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
---
22
---
14
qapi/block-core.json | 12 ++++++++
23
include/qemu/units.h | 18 ++++++++++++++++++
15
include/block/block_int.h | 5 +++-
24
1 file changed, 18 insertions(+)
16
block/create.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
17
block/qcow2.c | 1 +
18
block/Makefile.objs | 2 +-
19
5 files changed, 94 insertions(+), 2 deletions(-)
20
create mode 100644 block/create.c
21
25
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
26
diff --git a/include/qemu/units.h b/include/qemu/units.h
23
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
24
--- a/qapi/block-core.json
28
--- a/include/qemu/units.h
25
+++ b/qapi/block-core.json
29
+++ b/include/qemu/units.h
26
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
27
} }
31
#define PiB (INT64_C(1) << 50)
28
32
#define EiB (INT64_C(1) << 60)
29
##
33
30
+# @x-blockdev-create:
31
+#
32
+# Create an image format on a given node.
33
+# TODO Replace with something asynchronous (block job?)
34
+#
35
+# Since: 2.12
36
+##
37
+{ 'command': 'x-blockdev-create',
38
+ 'data': 'BlockdevCreateOptions',
39
+ 'boxed': true }
40
+
41
+##
42
# @blockdev-open-tray:
43
#
44
# Opens a block device's tray. If there is a block driver state tree inserted as
45
diff --git a/include/block/block_int.h b/include/block/block_int.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/block/block_int.h
48
+++ b/include/block/block_int.h
49
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
50
int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
51
Error **errp);
52
void (*bdrv_close)(BlockDriverState *bs);
53
- int coroutine_fn (*bdrv_co_create_opts)(const char *filename, QemuOpts *opts,
54
+ int coroutine_fn (*bdrv_co_create)(BlockdevCreateOptions *opts,
55
Error **errp);
56
+ int coroutine_fn (*bdrv_co_create_opts)(const char *filename,
57
+ QemuOpts *opts,
58
+ Error **errp);
59
int (*bdrv_make_empty)(BlockDriverState *bs);
60
61
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
62
diff --git a/block/create.c b/block/create.c
63
new file mode 100644
64
index XXXXXXX..XXXXXXX
65
--- /dev/null
66
+++ b/block/create.c
67
@@ -XXX,XX +XXX,XX @@
68
+/*
34
+/*
69
+ * Block layer code related to image creation
35
+ * The following lookup table is intended to be used when a literal string of
36
+ * the number of bytes is required (for example if it needs to be stringified).
37
+ * It can also be used for generic shortcuts of power-of-two sizes.
38
+ * This table is generated using the AWK script below:
70
+ *
39
+ *
71
+ * Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
40
+ * BEGIN {
72
+ *
41
+ * suffix="KMGTPE";
73
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * for(i=10; i<64; i++) {
74
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * val=2**i;
75
+ * in the Software without restriction, including without limitation the rights
44
+ * s=substr(suffix, int(i/10), 1);
76
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * n=2**(i%10);
77
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * pad=21-int(log(n)/log(10));
78
+ * furnished to do so, subject to the following conditions:
47
+ * printf("#define S_%d%siB %*d\n", n, s, pad, val);
79
+ *
48
+ * }
80
+ * The above copyright notice and this permission notice shall be included in
49
+ * }
81
+ * all copies or substantial portions of the Software.
82
+ *
83
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
86
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
89
+ * THE SOFTWARE.
90
+ */
50
+ */
91
+
51
+
92
+#include "qemu/osdep.h"
52
#define S_1KiB 1024
93
+#include "block/block_int.h"
53
#define S_2KiB 2048
94
+#include "qapi/qapi-commands-block-core.h"
54
#define S_4KiB 4096
95
+#include "qapi/error.h"
96
+
97
+typedef struct BlockdevCreateCo {
98
+ BlockDriver *drv;
99
+ BlockdevCreateOptions *opts;
100
+ int ret;
101
+ Error **errp;
102
+} BlockdevCreateCo;
103
+
104
+static void coroutine_fn bdrv_co_create_co_entry(void *opaque)
105
+{
106
+ BlockdevCreateCo *cco = opaque;
107
+ cco->ret = cco->drv->bdrv_co_create(cco->opts, cco->errp);
108
+}
109
+
110
+void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
111
+{
112
+ const char *fmt = BlockdevDriver_str(options->driver);
113
+ BlockDriver *drv = bdrv_find_format(fmt);
114
+ Coroutine *co;
115
+ BlockdevCreateCo cco;
116
+
117
+ /* If the driver is in the schema, we know that it exists. But it may not
118
+ * be whitelisted. */
119
+ assert(drv);
120
+ if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
121
+ error_setg(errp, "Driver is not whitelisted");
122
+ return;
123
+ }
124
+
125
+ /* Call callback if it exists */
126
+ if (!drv->bdrv_co_create) {
127
+ error_setg(errp, "Driver does not support blockdev-create");
128
+ return;
129
+ }
130
+
131
+ cco = (BlockdevCreateCo) {
132
+ .drv = drv,
133
+ .opts = options,
134
+ .ret = -EINPROGRESS,
135
+ .errp = errp,
136
+ };
137
+
138
+ co = qemu_coroutine_create(bdrv_co_create_co_entry, &cco);
139
+ qemu_coroutine_enter(co);
140
+ while (cco.ret == -EINPROGRESS) {
141
+ aio_poll(qemu_get_aio_context(), true);
142
+ }
143
+}
144
diff --git a/block/qcow2.c b/block/qcow2.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/block/qcow2.c
147
+++ b/block/qcow2.c
148
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
149
.bdrv_join_options = qcow2_join_options,
150
.bdrv_child_perm = bdrv_format_default_perms,
151
.bdrv_co_create_opts = qcow2_co_create_opts,
152
+ .bdrv_co_create = qcow2_co_create,
153
.bdrv_has_zero_init = bdrv_has_zero_init_1,
154
.bdrv_co_block_status = qcow2_co_block_status,
155
156
diff --git a/block/Makefile.objs b/block/Makefile.objs
157
index XXXXXXX..XXXXXXX 100644
158
--- a/block/Makefile.objs
159
+++ b/block/Makefile.objs
160
@@ -XXX,XX +XXX,XX @@ block-obj-y += block-backend.o snapshot.o qapi.o
161
block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
162
block-obj-$(CONFIG_POSIX) += file-posix.o
163
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
164
-block-obj-y += null.o mirror.o commit.o io.o
165
+block-obj-y += null.o mirror.o commit.o io.o create.o
166
block-obj-y += throttle-groups.o
167
block-obj-$(CONFIG_LINUX) += nvme.o
168
169
--
55
--
170
2.13.6
56
2.19.1
171
57
172
58
diff view generated by jsdifflib
Deleted patch
1
If we want to include the invalid option name in the error message, we
2
can't free the string earlier than that.
3
1
4
Cc: qemu-stable@nongnu.org
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
---
9
block/rbd.c | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/block/rbd.c b/block/rbd.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/rbd.c
15
+++ b/block/rbd.c
16
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs_json,
17
key = qstring_get_str(name);
18
19
ret = rados_conf_set(cluster, key, qstring_get_str(value));
20
- QDECREF(name);
21
QDECREF(value);
22
if (ret < 0) {
23
error_setg_errno(errp, -ret, "invalid conf option %s", key);
24
+ QDECREF(name);
25
ret = -EINVAL;
26
break;
27
}
28
+ QDECREF(name);
29
}
30
31
QDECREF(keypairs);
32
--
33
2.13.6
34
35
diff view generated by jsdifflib
Deleted patch
1
The code to establish an RBD connection is duplicated between open and
2
create. In order to be able to share the code, factor out the code from
3
qemu_rbd_open() as a first step.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
8
block/rbd.c | 100 ++++++++++++++++++++++++++++++++++++------------------------
9
1 file changed, 60 insertions(+), 40 deletions(-)
10
11
diff --git a/block/rbd.c b/block/rbd.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/rbd.c
14
+++ b/block/rbd.c
15
@@ -XXX,XX +XXX,XX @@ out:
16
return rados_str;
17
}
18
19
-static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
20
- Error **errp)
21
+static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
22
+ char **s_snap, char **s_image_name,
23
+ QDict *options, bool cache, Error **errp)
24
{
25
- BDRVRBDState *s = bs->opaque;
26
- const char *pool, *snap, *conf, *user, *image_name, *keypairs;
27
- const char *secretid, *filename;
28
QemuOpts *opts;
29
- Error *local_err = NULL;
30
char *mon_host = NULL;
31
+ const char *pool, *snap, *conf, *user, *image_name, *keypairs;
32
+ const char *secretid;
33
+ Error *local_err = NULL;
34
int r;
35
36
- /* If we are given a filename, parse the filename, with precedence given to
37
- * filename encoded options */
38
- filename = qdict_get_try_str(options, "filename");
39
- if (filename) {
40
- warn_report("'filename' option specified. "
41
- "This is an unsupported option, and may be deprecated "
42
- "in the future");
43
- qemu_rbd_parse_filename(filename, options, &local_err);
44
- if (local_err) {
45
- r = -EINVAL;
46
- error_propagate(errp, local_err);
47
- goto exit;
48
- }
49
- }
50
-
51
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
52
qemu_opts_absorb_qdict(opts, options, &local_err);
53
if (local_err) {
54
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
55
goto failed_opts;
56
}
57
58
- r = rados_create(&s->cluster, user);
59
+ r = rados_create(cluster, user);
60
if (r < 0) {
61
error_setg_errno(errp, -r, "error initializing");
62
goto failed_opts;
63
}
64
65
- s->snap = g_strdup(snap);
66
- s->image_name = g_strdup(image_name);
67
+ *s_snap = g_strdup(snap);
68
+ *s_image_name = g_strdup(image_name);
69
70
/* try default location when conf=NULL, but ignore failure */
71
- r = rados_conf_read_file(s->cluster, conf);
72
+ r = rados_conf_read_file(*cluster, conf);
73
if (conf && r < 0) {
74
error_setg_errno(errp, -r, "error reading conf file %s", conf);
75
goto failed_shutdown;
76
}
77
78
- r = qemu_rbd_set_keypairs(s->cluster, keypairs, errp);
79
+ r = qemu_rbd_set_keypairs(*cluster, keypairs, errp);
80
if (r < 0) {
81
goto failed_shutdown;
82
}
83
84
if (mon_host) {
85
- r = rados_conf_set(s->cluster, "mon_host", mon_host);
86
+ r = rados_conf_set(*cluster, "mon_host", mon_host);
87
if (r < 0) {
88
goto failed_shutdown;
89
}
90
}
91
92
- if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) {
93
+ if (qemu_rbd_set_auth(*cluster, secretid, errp) < 0) {
94
r = -EIO;
95
goto failed_shutdown;
96
}
97
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
98
* librbd defaults to no caching. If write through caching cannot
99
* be set up, fall back to no caching.
100
*/
101
- if (flags & BDRV_O_NOCACHE) {
102
- rados_conf_set(s->cluster, "rbd_cache", "false");
103
+ if (cache) {
104
+ rados_conf_set(*cluster, "rbd_cache", "true");
105
} else {
106
- rados_conf_set(s->cluster, "rbd_cache", "true");
107
+ rados_conf_set(*cluster, "rbd_cache", "false");
108
}
109
110
- r = rados_connect(s->cluster);
111
+ r = rados_connect(*cluster);
112
if (r < 0) {
113
error_setg_errno(errp, -r, "error connecting");
114
goto failed_shutdown;
115
}
116
117
- r = rados_ioctx_create(s->cluster, pool, &s->io_ctx);
118
+ r = rados_ioctx_create(*cluster, pool, io_ctx);
119
if (r < 0) {
120
error_setg_errno(errp, -r, "error opening pool %s", pool);
121
goto failed_shutdown;
122
}
123
124
+ qemu_opts_del(opts);
125
+ return 0;
126
+
127
+failed_shutdown:
128
+ rados_shutdown(*cluster);
129
+ g_free(*s_snap);
130
+ g_free(*s_image_name);
131
+failed_opts:
132
+ qemu_opts_del(opts);
133
+ g_free(mon_host);
134
+ return r;
135
+}
136
+
137
+static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
138
+ Error **errp)
139
+{
140
+ BDRVRBDState *s = bs->opaque;
141
+ Error *local_err = NULL;
142
+ const char *filename;
143
+ int r;
144
+
145
+ /* If we are given a filename, parse the filename, with precedence given to
146
+ * filename encoded options */
147
+ filename = qdict_get_try_str(options, "filename");
148
+ if (filename) {
149
+ warn_report("'filename' option specified. "
150
+ "This is an unsupported option, and may be deprecated "
151
+ "in the future");
152
+ qemu_rbd_parse_filename(filename, options, &local_err);
153
+ if (local_err) {
154
+ error_propagate(errp, local_err);
155
+ return -EINVAL;
156
+ }
157
+ }
158
+
159
+ r = qemu_rbd_connect(&s->cluster, &s->io_ctx, &s->snap, &s->image_name,
160
+ options, !(flags & BDRV_O_NOCACHE), errp);
161
+ if (r < 0) {
162
+ return r;
163
+ }
164
+
165
/* rbd_open is always r/w */
166
r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
167
if (r < 0) {
168
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
169
}
170
}
171
172
- qemu_opts_del(opts);
173
return 0;
174
175
failed_open:
176
rados_ioctx_destroy(s->io_ctx);
177
-failed_shutdown:
178
- rados_shutdown(s->cluster);
179
g_free(s->snap);
180
g_free(s->image_name);
181
-failed_opts:
182
- qemu_opts_del(opts);
183
- g_free(mon_host);
184
-exit:
185
+ rados_shutdown(s->cluster);
186
return r;
187
}
188
189
--
190
2.13.6
191
192
diff view generated by jsdifflib
Deleted patch
1
Instead of the QemuOpts in qemu_rbd_connect(), we want to use QAPI
2
objects. As a preparation, fetch those options directly from the QDict
3
that .bdrv_open() supports in the rbd driver and that are not in the
4
schema.
5
1
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/rbd.c | 55 ++++++++++++++++++++++++-------------------------------
10
1 file changed, 24 insertions(+), 31 deletions(-)
11
12
diff --git a/block/rbd.c b/block/rbd.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/rbd.c
15
+++ b/block/rbd.c
16
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
17
/*
18
* server.* extracted manually, see qemu_rbd_mon_host()
19
*/
20
- {
21
- .name = "password-secret",
22
- .type = QEMU_OPT_STRING,
23
- .help = "ID of secret providing the password",
24
- },
25
-
26
- /*
27
- * Keys for qemu_rbd_parse_filename(), not in the QAPI schema
28
- */
29
- {
30
- /*
31
- * HACK: name starts with '=' so that qemu_opts_parse()
32
- * can't set it
33
- */
34
- .name = "=keyvalue-pairs",
35
- .type = QEMU_OPT_STRING,
36
- .help = "Legacy rados key/value option parameters",
37
- },
38
- {
39
- .name = "filename",
40
- .type = QEMU_OPT_STRING,
41
- },
42
{ /* end of list */ }
43
},
44
};
45
@@ -XXX,XX +XXX,XX @@ out:
46
47
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
48
char **s_snap, char **s_image_name,
49
- QDict *options, bool cache, Error **errp)
50
+ QDict *options, bool cache,
51
+ const char *keypairs, const char *secretid,
52
+ Error **errp)
53
{
54
QemuOpts *opts;
55
char *mon_host = NULL;
56
- const char *pool, *snap, *conf, *user, *image_name, *keypairs;
57
- const char *secretid;
58
+ const char *pool, *snap, *conf, *user, *image_name;
59
Error *local_err = NULL;
60
int r;
61
62
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
63
goto failed_opts;
64
}
65
66
- secretid = qemu_opt_get(opts, "password-secret");
67
-
68
pool = qemu_opt_get(opts, "pool");
69
conf = qemu_opt_get(opts, "conf");
70
snap = qemu_opt_get(opts, "snapshot");
71
user = qemu_opt_get(opts, "user");
72
image_name = qemu_opt_get(opts, "image");
73
- keypairs = qemu_opt_get(opts, "=keyvalue-pairs");
74
75
if (!pool || !image_name) {
76
error_setg(errp, "Parameters 'pool' and 'image' are required");
77
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
78
BDRVRBDState *s = bs->opaque;
79
Error *local_err = NULL;
80
const char *filename;
81
+ char *keypairs, *secretid;
82
int r;
83
84
/* If we are given a filename, parse the filename, with precedence given to
85
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
86
"This is an unsupported option, and may be deprecated "
87
"in the future");
88
qemu_rbd_parse_filename(filename, options, &local_err);
89
+ qdict_del(options, "filename");
90
if (local_err) {
91
error_propagate(errp, local_err);
92
return -EINVAL;
93
}
94
}
95
96
+ keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs"));
97
+ if (keypairs) {
98
+ qdict_del(options, "=keyvalue-pairs");
99
+ }
100
+
101
+ secretid = g_strdup(qdict_get_try_str(options, "password-secret"));
102
+ if (secretid) {
103
+ qdict_del(options, "password-secret");
104
+ }
105
+
106
r = qemu_rbd_connect(&s->cluster, &s->io_ctx, &s->snap, &s->image_name,
107
- options, !(flags & BDRV_O_NOCACHE), errp);
108
+ options, !(flags & BDRV_O_NOCACHE), keypairs, secretid,
109
+ errp);
110
if (r < 0) {
111
- return r;
112
+ goto out;
113
}
114
115
/* rbd_open is always r/w */
116
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
117
}
118
}
119
120
- return 0;
121
+ r = 0;
122
+ goto out;
123
124
failed_open:
125
rados_ioctx_destroy(s->io_ctx);
126
g_free(s->snap);
127
g_free(s->image_name);
128
rados_shutdown(s->cluster);
129
+out:
130
+ g_free(keypairs);
131
+ g_free(secretid);
132
return r;
133
}
134
135
--
136
2.13.6
137
138
diff view generated by jsdifflib
Deleted patch
1
With the conversion to a QAPI options object, the function is now
2
prepared to be used in a .bdrv_co_create implementation.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
block/rbd.c | 115 +++++++++++++++++++++++++++++-------------------------------
8
1 file changed, 55 insertions(+), 60 deletions(-)
9
10
diff --git a/block/rbd.c b/block/rbd.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/rbd.c
13
+++ b/block/rbd.c
14
@@ -XXX,XX +XXX,XX @@
15
#include "qapi/qmp/qdict.h"
16
#include "qapi/qmp/qjson.h"
17
#include "qapi/qmp/qlist.h"
18
+#include "qapi/qobject-input-visitor.h"
19
+#include "qapi/qapi-visit-block-core.h"
20
21
/*
22
* When specifying the image filename use:
23
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
24
qemu_aio_unref(acb);
25
}
26
27
-static char *qemu_rbd_mon_host(QDict *options, Error **errp)
28
+static char *qemu_rbd_mon_host(BlockdevOptionsRbd *opts, Error **errp)
29
{
30
- const char **vals = g_new(const char *, qdict_size(options) + 1);
31
- char keybuf[32];
32
+ const char **vals;
33
const char *host, *port;
34
char *rados_str;
35
- int i;
36
-
37
- for (i = 0;; i++) {
38
- sprintf(keybuf, "server.%d.host", i);
39
- host = qdict_get_try_str(options, keybuf);
40
- qdict_del(options, keybuf);
41
- sprintf(keybuf, "server.%d.port", i);
42
- port = qdict_get_try_str(options, keybuf);
43
- qdict_del(options, keybuf);
44
- if (!host && !port) {
45
- break;
46
- }
47
- if (!host) {
48
- error_setg(errp, "Parameter server.%d.host is missing", i);
49
- rados_str = NULL;
50
- goto out;
51
- }
52
+ InetSocketAddressBaseList *p;
53
+ int i, cnt;
54
+
55
+ if (!opts->has_server) {
56
+ return NULL;
57
+ }
58
+
59
+ for (cnt = 0, p = opts->server; p; p = p->next) {
60
+ cnt++;
61
+ }
62
+
63
+ vals = g_new(const char *, cnt + 1);
64
+
65
+ for (i = 0, p = opts->server; p; p = p->next, i++) {
66
+ host = p->value->host;
67
+ port = p->value->port;
68
69
if (strchr(host, ':')) {
70
- vals[i] = port ? g_strdup_printf("[%s]:%s", host, port)
71
- : g_strdup_printf("[%s]", host);
72
+ vals[i] = g_strdup_printf("[%s]:%s", host, port);
73
} else {
74
- vals[i] = port ? g_strdup_printf("%s:%s", host, port)
75
- : g_strdup(host);
76
+ vals[i] = g_strdup_printf("%s:%s", host, port);
77
}
78
}
79
vals[i] = NULL;
80
81
rados_str = i ? g_strjoinv(";", (char **)vals) : NULL;
82
-out:
83
g_strfreev((char **)vals);
84
return rados_str;
85
}
86
87
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
88
char **s_snap, char **s_image_name,
89
- QDict *options, bool cache,
90
+ BlockdevOptionsRbd *opts, bool cache,
91
const char *keypairs, const char *secretid,
92
Error **errp)
93
{
94
- QemuOpts *opts;
95
char *mon_host = NULL;
96
- const char *pool, *snap, *conf, *user, *image_name;
97
Error *local_err = NULL;
98
int r;
99
100
- opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
101
- qemu_opts_absorb_qdict(opts, options, &local_err);
102
- if (local_err) {
103
- error_propagate(errp, local_err);
104
- r = -EINVAL;
105
- goto failed_opts;
106
- }
107
-
108
- mon_host = qemu_rbd_mon_host(options, &local_err);
109
+ mon_host = qemu_rbd_mon_host(opts, &local_err);
110
if (local_err) {
111
error_propagate(errp, local_err);
112
r = -EINVAL;
113
goto failed_opts;
114
}
115
116
- pool = qemu_opt_get(opts, "pool");
117
- conf = qemu_opt_get(opts, "conf");
118
- snap = qemu_opt_get(opts, "snapshot");
119
- user = qemu_opt_get(opts, "user");
120
- image_name = qemu_opt_get(opts, "image");
121
-
122
- if (!pool || !image_name) {
123
- error_setg(errp, "Parameters 'pool' and 'image' are required");
124
- r = -EINVAL;
125
- goto failed_opts;
126
- }
127
-
128
- r = rados_create(cluster, user);
129
+ r = rados_create(cluster, opts->user);
130
if (r < 0) {
131
error_setg_errno(errp, -r, "error initializing");
132
goto failed_opts;
133
}
134
135
- *s_snap = g_strdup(snap);
136
- *s_image_name = g_strdup(image_name);
137
+ *s_snap = g_strdup(opts->snapshot);
138
+ *s_image_name = g_strdup(opts->image);
139
140
/* try default location when conf=NULL, but ignore failure */
141
- r = rados_conf_read_file(*cluster, conf);
142
- if (conf && r < 0) {
143
- error_setg_errno(errp, -r, "error reading conf file %s", conf);
144
+ r = rados_conf_read_file(*cluster, opts->conf);
145
+ if (opts->has_conf && r < 0) {
146
+ error_setg_errno(errp, -r, "error reading conf file %s", opts->conf);
147
goto failed_shutdown;
148
}
149
150
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
151
goto failed_shutdown;
152
}
153
154
- r = rados_ioctx_create(*cluster, pool, io_ctx);
155
+ r = rados_ioctx_create(*cluster, opts->pool, io_ctx);
156
if (r < 0) {
157
- error_setg_errno(errp, -r, "error opening pool %s", pool);
158
+ error_setg_errno(errp, -r, "error opening pool %s", opts->pool);
159
goto failed_shutdown;
160
}
161
162
- qemu_opts_del(opts);
163
return 0;
164
165
failed_shutdown:
166
@@ -XXX,XX +XXX,XX @@ failed_shutdown:
167
g_free(*s_snap);
168
g_free(*s_image_name);
169
failed_opts:
170
- qemu_opts_del(opts);
171
g_free(mon_host);
172
return r;
173
}
174
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
175
Error **errp)
176
{
177
BDRVRBDState *s = bs->opaque;
178
+ BlockdevOptionsRbd *opts = NULL;
179
+ Visitor *v;
180
+ QObject *crumpled = NULL;
181
Error *local_err = NULL;
182
const char *filename;
183
char *keypairs, *secretid;
184
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
185
qdict_del(options, "password-secret");
186
}
187
188
+ /* Convert the remaining options into a QAPI object */
189
+ crumpled = qdict_crumple(options, errp);
190
+ if (crumpled == NULL) {
191
+ r = -EINVAL;
192
+ goto out;
193
+ }
194
+
195
+ v = qobject_input_visitor_new_keyval(crumpled);
196
+ visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err);
197
+ visit_free(v);
198
+ qobject_decref(crumpled);
199
+
200
+ if (local_err) {
201
+ error_propagate(errp, local_err);
202
+ r = -EINVAL;
203
+ goto out;
204
+ }
205
+
206
r = qemu_rbd_connect(&s->cluster, &s->io_ctx, &s->snap, &s->image_name,
207
- options, !(flags & BDRV_O_NOCACHE), keypairs, secretid,
208
+ opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid,
209
errp);
210
if (r < 0) {
211
goto out;
212
@@ -XXX,XX +XXX,XX @@ failed_open:
213
g_free(s->image_name);
214
rados_shutdown(s->cluster);
215
out:
216
+ qapi_free_BlockdevOptionsRbd(opts);
217
g_free(keypairs);
218
g_free(secretid);
219
return r;
220
--
221
2.13.6
222
223
diff view generated by jsdifflib
Deleted patch
1
This adds the .bdrv_co_create driver callback to rbd, which enables
2
image creation over QMP.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
qapi/block-core.json | 19 ++++++-
8
block/rbd.c | 150 ++++++++++++++++++++++++++++++++++-----------------
9
2 files changed, 118 insertions(+), 51 deletions(-)
10
11
diff --git a/qapi/block-core.json b/qapi/block-core.json
12
index XXXXXXX..XXXXXXX 100644
13
--- a/qapi/block-core.json
14
+++ b/qapi/block-core.json
15
@@ -XXX,XX +XXX,XX @@
16
'*refcount-bits': 'int' } }
17
18
##
19
+# @BlockdevCreateOptionsRbd:
20
+#
21
+# Driver specific image creation options for rbd/Ceph.
22
+#
23
+# @location Where to store the new image file. This location cannot
24
+# point to a snapshot.
25
+# @size Size of the virtual disk in bytes
26
+# @cluster-size RBD object size
27
+#
28
+# Since: 2.12
29
+##
30
+{ 'struct': 'BlockdevCreateOptionsRbd',
31
+ 'data': { 'location': 'BlockdevOptionsRbd',
32
+ 'size': 'size',
33
+ '*cluster-size' : 'size' } }
34
+
35
+##
36
# @BlockdevCreateNotSupported:
37
#
38
# This is used for all drivers that don't support creating images.
39
@@ -XXX,XX +XXX,XX @@
40
'qed': 'BlockdevCreateNotSupported',
41
'quorum': 'BlockdevCreateNotSupported',
42
'raw': 'BlockdevCreateNotSupported',
43
- 'rbd': 'BlockdevCreateNotSupported',
44
+ 'rbd': 'BlockdevCreateOptionsRbd',
45
'replication': 'BlockdevCreateNotSupported',
46
'sheepdog': 'BlockdevCreateNotSupported',
47
'ssh': 'BlockdevCreateNotSupported',
48
diff --git a/block/rbd.c b/block/rbd.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/rbd.c
51
+++ b/block/rbd.c
52
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
53
},
54
};
55
56
-static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
57
- QemuOpts *opts,
58
- Error **errp)
59
+/* FIXME Deprecate and remove keypairs or make it available in QMP.
60
+ * password_secret should eventually be configurable in opts->location. Support
61
+ * for it in .bdrv_open will make it work here as well. */
62
+static int qemu_rbd_do_create(BlockdevCreateOptions *options,
63
+ const char *keypairs, const char *password_secret,
64
+ Error **errp)
65
{
66
- Error *local_err = NULL;
67
- int64_t bytes = 0;
68
- int64_t objsize;
69
- int obj_order = 0;
70
- const char *pool, *image_name, *conf, *user, *keypairs;
71
- const char *secretid;
72
+ BlockdevCreateOptionsRbd *opts = &options->u.rbd;
73
rados_t cluster;
74
rados_ioctx_t io_ctx;
75
- QDict *options = NULL;
76
- int ret = 0;
77
+ int obj_order = 0;
78
+ int ret;
79
+
80
+ assert(options->driver == BLOCKDEV_DRIVER_RBD);
81
+ if (opts->location->has_snapshot) {
82
+ error_setg(errp, "Can't use snapshot name for image creation");
83
+ return -EINVAL;
84
+ }
85
86
- secretid = qemu_opt_get(opts, "password-secret");
87
+ /* TODO Remove the limitation */
88
+ if (opts->location->has_server) {
89
+ error_setg(errp, "Can't specify server for image creation");
90
+ return -EINVAL;
91
+ }
92
93
- /* Read out options */
94
- bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
95
- BDRV_SECTOR_SIZE);
96
- objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0);
97
- if (objsize) {
98
+ if (opts->has_cluster_size) {
99
+ int64_t objsize = opts->cluster_size;
100
if ((objsize - 1) & objsize) { /* not a power of 2? */
101
error_setg(errp, "obj size needs to be power of 2");
102
- ret = -EINVAL;
103
- goto exit;
104
+ return -EINVAL;
105
}
106
if (objsize < 4096) {
107
error_setg(errp, "obj size too small");
108
- ret = -EINVAL;
109
- goto exit;
110
+ return -EINVAL;
111
}
112
obj_order = ctz32(objsize);
113
}
114
115
- options = qdict_new();
116
- qemu_rbd_parse_filename(filename, options, &local_err);
117
- if (local_err) {
118
- ret = -EINVAL;
119
- error_propagate(errp, local_err);
120
- goto exit;
121
- }
122
-
123
- /*
124
- * Caution: while qdict_get_try_str() is fine, getting non-string
125
- * types would require more care. When @options come from -blockdev
126
- * or blockdev_add, its members are typed according to the QAPI
127
- * schema, but when they come from -drive, they're all QString.
128
- */
129
- pool = qdict_get_try_str(options, "pool");
130
- conf = qdict_get_try_str(options, "conf");
131
- user = qdict_get_try_str(options, "user");
132
- image_name = qdict_get_try_str(options, "image");
133
- keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
134
-
135
- ret = rados_create(&cluster, user);
136
+ ret = rados_create(&cluster, opts->location->user);
137
if (ret < 0) {
138
error_setg_errno(errp, -ret, "error initializing");
139
- goto exit;
140
+ return ret;
141
}
142
143
/* try default location when conf=NULL, but ignore failure */
144
- ret = rados_conf_read_file(cluster, conf);
145
- if (conf && ret < 0) {
146
- error_setg_errno(errp, -ret, "error reading conf file %s", conf);
147
+ ret = rados_conf_read_file(cluster, opts->location->conf);
148
+ if (opts->location->conf && ret < 0) {
149
+ error_setg_errno(errp, -ret, "error reading conf file %s",
150
+ opts->location->conf);
151
ret = -EIO;
152
goto shutdown;
153
}
154
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
155
goto shutdown;
156
}
157
158
- if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) {
159
+ if (qemu_rbd_set_auth(cluster, password_secret, errp) < 0) {
160
ret = -EIO;
161
goto shutdown;
162
}
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
164
goto shutdown;
165
}
166
167
- ret = rados_ioctx_create(cluster, pool, &io_ctx);
168
+ ret = rados_ioctx_create(cluster, opts->location->pool, &io_ctx);
169
if (ret < 0) {
170
- error_setg_errno(errp, -ret, "error opening pool %s", pool);
171
+ error_setg_errno(errp, -ret, "error opening pool %s",
172
+ opts->location->pool);
173
goto shutdown;
174
}
175
176
- ret = rbd_create(io_ctx, image_name, bytes, &obj_order);
177
+ ret = rbd_create(io_ctx, opts->location->image, opts->size, &obj_order);
178
if (ret < 0) {
179
error_setg_errno(errp, -ret, "error rbd create");
180
}
181
182
rados_ioctx_destroy(io_ctx);
183
184
+ ret = 0;
185
shutdown:
186
rados_shutdown(cluster);
187
+ return ret;
188
+}
189
+
190
+static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp)
191
+{
192
+ return qemu_rbd_do_create(options, NULL, NULL, errp);
193
+}
194
+
195
+static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
196
+ QemuOpts *opts,
197
+ Error **errp)
198
+{
199
+ BlockdevCreateOptions *create_options;
200
+ BlockdevCreateOptionsRbd *rbd_opts;
201
+ BlockdevOptionsRbd *loc;
202
+ Error *local_err = NULL;
203
+ const char *keypairs, *password_secret;
204
+ QDict *options = NULL;
205
+ int ret = 0;
206
+
207
+ create_options = g_new0(BlockdevCreateOptions, 1);
208
+ create_options->driver = BLOCKDEV_DRIVER_RBD;
209
+ rbd_opts = &create_options->u.rbd;
210
+
211
+ rbd_opts->location = g_new0(BlockdevOptionsRbd, 1);
212
+
213
+ password_secret = qemu_opt_get(opts, "password-secret");
214
+
215
+ /* Read out options */
216
+ rbd_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
217
+ BDRV_SECTOR_SIZE);
218
+ rbd_opts->cluster_size = qemu_opt_get_size_del(opts,
219
+ BLOCK_OPT_CLUSTER_SIZE, 0);
220
+ rbd_opts->has_cluster_size = (rbd_opts->cluster_size != 0);
221
+
222
+ options = qdict_new();
223
+ qemu_rbd_parse_filename(filename, options, &local_err);
224
+ if (local_err) {
225
+ ret = -EINVAL;
226
+ error_propagate(errp, local_err);
227
+ goto exit;
228
+ }
229
+
230
+ /*
231
+ * Caution: while qdict_get_try_str() is fine, getting non-string
232
+ * types would require more care. When @options come from -blockdev
233
+ * or blockdev_add, its members are typed according to the QAPI
234
+ * schema, but when they come from -drive, they're all QString.
235
+ */
236
+ loc = rbd_opts->location;
237
+ loc->pool = g_strdup(qdict_get_try_str(options, "pool"));
238
+ loc->conf = g_strdup(qdict_get_try_str(options, "conf"));
239
+ loc->has_conf = !!loc->conf;
240
+ loc->user = g_strdup(qdict_get_try_str(options, "user"));
241
+ loc->has_user = !!loc->user;
242
+ loc->image = g_strdup(qdict_get_try_str(options, "image"));
243
+ keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
244
+
245
+ ret = qemu_rbd_do_create(create_options, keypairs, password_secret, errp);
246
+ if (ret < 0) {
247
+ goto exit;
248
+ }
249
250
exit:
251
QDECREF(options);
252
+ qapi_free_BlockdevCreateOptions(create_options);
253
return ret;
254
}
255
256
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
257
.bdrv_file_open = qemu_rbd_open,
258
.bdrv_close = qemu_rbd_close,
259
.bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
260
+ .bdrv_co_create = qemu_rbd_co_create,
261
.bdrv_co_create_opts = qemu_rbd_co_create_opts,
262
.bdrv_has_zero_init = bdrv_has_zero_init_1,
263
.bdrv_get_info = qemu_rbd_getinfo,
264
--
265
2.13.6
266
267
diff view generated by jsdifflib
Deleted patch
1
Now that the options are already available in qemu_rbd_open() and not
2
only parsed in qemu_rbd_connect(), we can assign s->snap and
3
s->image_name there instead of passing the fields by reference to
4
qemu_rbd_connect().
5
1
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
---
9
block/rbd.c | 14 +++++---------
10
1 file changed, 5 insertions(+), 9 deletions(-)
11
12
diff --git a/block/rbd.c b/block/rbd.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/rbd.c
15
+++ b/block/rbd.c
16
@@ -XXX,XX +XXX,XX @@ static char *qemu_rbd_mon_host(BlockdevOptionsRbd *opts, Error **errp)
17
}
18
19
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
20
- char **s_snap, char **s_image_name,
21
BlockdevOptionsRbd *opts, bool cache,
22
const char *keypairs, const char *secretid,
23
Error **errp)
24
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
25
goto failed_opts;
26
}
27
28
- *s_snap = g_strdup(opts->snapshot);
29
- *s_image_name = g_strdup(opts->image);
30
-
31
/* try default location when conf=NULL, but ignore failure */
32
r = rados_conf_read_file(*cluster, opts->conf);
33
if (opts->has_conf && r < 0) {
34
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
35
36
failed_shutdown:
37
rados_shutdown(*cluster);
38
- g_free(*s_snap);
39
- g_free(*s_image_name);
40
failed_opts:
41
g_free(mon_host);
42
return r;
43
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
44
goto out;
45
}
46
47
- r = qemu_rbd_connect(&s->cluster, &s->io_ctx, &s->snap, &s->image_name,
48
- opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid,
49
- errp);
50
+ r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts,
51
+ !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp);
52
if (r < 0) {
53
goto out;
54
}
55
56
+ s->snap = g_strdup(opts->snapshot);
57
+ s->image_name = g_strdup(opts->image);
58
+
59
/* rbd_open is always r/w */
60
r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap);
61
if (r < 0) {
62
--
63
2.13.6
64
65
diff view generated by jsdifflib
Deleted patch
1
This adds the .bdrv_co_create driver callback to nfs, which enables
2
image creation over QMP.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
qapi/block-core.json | 16 ++++++++++-
8
block/nfs.c | 76 +++++++++++++++++++++++++++++++++++++++++-----------
9
2 files changed, 75 insertions(+), 17 deletions(-)
10
11
diff --git a/qapi/block-core.json b/qapi/block-core.json
12
index XXXXXXX..XXXXXXX 100644
13
--- a/qapi/block-core.json
14
+++ b/qapi/block-core.json
15
@@ -XXX,XX +XXX,XX @@
16
'*preallocation': 'PreallocMode' } }
17
18
##
19
+# @BlockdevCreateOptionsNfs:
20
+#
21
+# Driver specific image creation options for NFS.
22
+#
23
+# @location Where to store the new image file
24
+# @size Size of the virtual disk in bytes
25
+#
26
+# Since: 2.12
27
+##
28
+{ 'struct': 'BlockdevCreateOptionsNfs',
29
+ 'data': { 'location': 'BlockdevOptionsNfs',
30
+ 'size': 'size' } }
31
+
32
+##
33
# @BlockdevQcow2Version:
34
#
35
# @v2: The original QCOW2 format as introduced in qemu 0.10 (version 2)
36
@@ -XXX,XX +XXX,XX @@
37
'iscsi': 'BlockdevCreateNotSupported',
38
'luks': 'BlockdevCreateNotSupported',
39
'nbd': 'BlockdevCreateNotSupported',
40
- 'nfs': 'BlockdevCreateNotSupported',
41
+ 'nfs': 'BlockdevCreateOptionsNfs',
42
'null-aio': 'BlockdevCreateNotSupported',
43
'null-co': 'BlockdevCreateNotSupported',
44
'nvme': 'BlockdevCreateNotSupported',
45
diff --git a/block/nfs.c b/block/nfs.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/nfs.c
48
+++ b/block/nfs.c
49
@@ -XXX,XX +XXX,XX @@ out:
50
return ret;
51
}
52
53
-static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
54
- int flags, int open_flags, Error **errp)
55
+static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QDict *options,
56
+ Error **errp)
57
{
58
BlockdevOptionsNfs *opts = NULL;
59
QObject *crumpled = NULL;
60
Visitor *v;
61
Error *local_err = NULL;
62
- int ret;
63
64
crumpled = qdict_crumple(options, errp);
65
if (crumpled == NULL) {
66
- return -EINVAL;
67
+ return NULL;
68
}
69
70
v = qobject_input_visitor_new_keyval(crumpled);
71
visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err);
72
visit_free(v);
73
+ qobject_decref(crumpled);
74
75
if (local_err) {
76
- error_propagate(errp, local_err);
77
+ return NULL;
78
+ }
79
+
80
+ return opts;
81
+}
82
+
83
+static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
84
+ int flags, int open_flags, Error **errp)
85
+{
86
+ BlockdevOptionsNfs *opts;
87
+ int ret;
88
+
89
+ opts = nfs_options_qdict_to_qapi(options, errp);
90
+ if (opts == NULL) {
91
ret = -EINVAL;
92
goto fail;
93
}
94
95
ret = nfs_client_open(client, opts, flags, open_flags, errp);
96
fail:
97
- qobject_decref(crumpled);
98
qapi_free_BlockdevOptionsNfs(opts);
99
return ret;
100
}
101
@@ -XXX,XX +XXX,XX @@ static QemuOptsList nfs_create_opts = {
102
}
103
};
104
105
-static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
106
- Error **errp)
107
+static int nfs_file_co_create(BlockdevCreateOptions *options, Error **errp)
108
{
109
- int64_t ret, total_size;
110
+ BlockdevCreateOptionsNfs *opts = &options->u.nfs;
111
NFSClient *client = g_new0(NFSClient, 1);
112
- QDict *options = NULL;
113
+ int ret;
114
+
115
+ assert(options->driver == BLOCKDEV_DRIVER_NFS);
116
117
client->aio_context = qemu_get_aio_context();
118
119
+ ret = nfs_client_open(client, opts->location, O_CREAT, 0, errp);
120
+ if (ret < 0) {
121
+ goto out;
122
+ }
123
+ ret = nfs_ftruncate(client->context, client->fh, opts->size);
124
+ nfs_client_close(client);
125
+
126
+out:
127
+ g_free(client);
128
+ return ret;
129
+}
130
+
131
+static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
132
+ Error **errp)
133
+{
134
+ BlockdevCreateOptions *create_options;
135
+ BlockdevCreateOptionsNfs *nfs_opts;
136
+ QDict *options;
137
+ int ret;
138
+
139
+ create_options = g_new0(BlockdevCreateOptions, 1);
140
+ create_options->driver = BLOCKDEV_DRIVER_NFS;
141
+ nfs_opts = &create_options->u.nfs;
142
+
143
/* Read out options */
144
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
145
- BDRV_SECTOR_SIZE);
146
+ nfs_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
147
+ BDRV_SECTOR_SIZE);
148
149
options = qdict_new();
150
ret = nfs_parse_uri(url, options, errp);
151
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nfs_file_co_create_opts(const char *url, QemuOpts *opts,
152
goto out;
153
}
154
155
- ret = nfs_client_open_qdict(client, options, O_CREAT, 0, errp);
156
+ nfs_opts->location = nfs_options_qdict_to_qapi(options, errp);
157
+ if (nfs_opts->location == NULL) {
158
+ ret = -EINVAL;
159
+ goto out;
160
+ }
161
+
162
+ ret = nfs_file_co_create(create_options, errp);
163
if (ret < 0) {
164
goto out;
165
}
166
- ret = nfs_ftruncate(client->context, client->fh, total_size);
167
- nfs_client_close(client);
168
+
169
+ ret = 0;
170
out:
171
QDECREF(options);
172
- g_free(client);
173
+ qapi_free_BlockdevCreateOptions(create_options);
174
return ret;
175
}
176
177
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nfs = {
178
179
.bdrv_file_open = nfs_file_open,
180
.bdrv_close = nfs_file_close,
181
+ .bdrv_co_create = nfs_file_co_create,
182
.bdrv_co_create_opts = nfs_file_co_create_opts,
183
.bdrv_reopen_prepare = nfs_reopen_prepare,
184
185
--
186
2.13.6
187
188
diff view generated by jsdifflib
Deleted patch
1
This adds the .bdrv_co_create driver callback to sheepdog, which enables
2
image creation over QMP.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
qapi/block-core.json | 24 ++++-
8
block/sheepdog.c | 243 +++++++++++++++++++++++++++++++++++----------------
9
2 files changed, 192 insertions(+), 75 deletions(-)
10
11
diff --git a/qapi/block-core.json b/qapi/block-core.json
12
index XXXXXXX..XXXXXXX 100644
13
--- a/qapi/block-core.json
14
+++ b/qapi/block-core.json
15
@@ -XXX,XX +XXX,XX @@
16
'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
17
18
##
19
+# @BlockdevCreateOptionsSheepdog:
20
+#
21
+# Driver specific image creation options for Sheepdog.
22
+#
23
+# @location Where to store the new image file
24
+# @size Size of the virtual disk in bytes
25
+# @backing-file File name of a base image
26
+# @preallocation Preallocation mode (allowed values: off, full)
27
+# @redundancy Redundancy of the image
28
+# @object-size Object size of the image
29
+#
30
+# Since: 2.12
31
+##
32
+{ 'struct': 'BlockdevCreateOptionsSheepdog',
33
+ 'data': { 'location': 'BlockdevOptionsSheepdog',
34
+ 'size': 'size',
35
+ '*backing-file': 'str',
36
+ '*preallocation': 'PreallocMode',
37
+ '*redundancy': 'SheepdogRedundancy',
38
+ '*object-size': 'size' } }
39
+
40
+##
41
# @BlockdevCreateNotSupported:
42
#
43
# This is used for all drivers that don't support creating images.
44
@@ -XXX,XX +XXX,XX @@
45
'raw': 'BlockdevCreateNotSupported',
46
'rbd': 'BlockdevCreateOptionsRbd',
47
'replication': 'BlockdevCreateNotSupported',
48
- 'sheepdog': 'BlockdevCreateNotSupported',
49
+ 'sheepdog': 'BlockdevCreateOptionsSheepdog',
50
'ssh': 'BlockdevCreateNotSupported',
51
'throttle': 'BlockdevCreateNotSupported',
52
'vdi': 'BlockdevCreateNotSupported',
53
diff --git a/block/sheepdog.c b/block/sheepdog.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/sheepdog.c
56
+++ b/block/sheepdog.c
57
@@ -XXX,XX +XXX,XX @@
58
#include "qemu/osdep.h"
59
#include "qapi/error.h"
60
#include "qapi/qapi-visit-sockets.h"
61
+#include "qapi/qapi-visit-block-core.h"
62
#include "qapi/qmp/qdict.h"
63
#include "qapi/qobject-input-visitor.h"
64
+#include "qapi/qobject-output-visitor.h"
65
#include "qemu/uri.h"
66
#include "qemu/error-report.h"
67
#include "qemu/option.h"
68
@@ -XXX,XX +XXX,XX @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
69
qemu_co_mutex_unlock(&s->queue_lock);
70
}
71
72
-static SocketAddress *sd_socket_address(const char *path,
73
- const char *host, const char *port)
74
-{
75
- SocketAddress *addr = g_new0(SocketAddress, 1);
76
-
77
- if (path) {
78
- addr->type = SOCKET_ADDRESS_TYPE_UNIX;
79
- addr->u.q_unix.path = g_strdup(path);
80
- } else {
81
- addr->type = SOCKET_ADDRESS_TYPE_INET;
82
- addr->u.inet.host = g_strdup(host ?: SD_DEFAULT_ADDR);
83
- addr->u.inet.port = g_strdup(port ?: stringify(SD_DEFAULT_PORT));
84
- }
85
-
86
- return addr;
87
-}
88
-
89
static SocketAddress *sd_server_config(QDict *options, Error **errp)
90
{
91
QDict *server = NULL;
92
@@ -XXX,XX +XXX,XX @@ out_with_err_set:
93
return ret;
94
}
95
96
+static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size,
97
+ Error **errp)
98
+{
99
+ BlockDriverState *bs;
100
+ Visitor *v;
101
+ QObject *obj = NULL;
102
+ QDict *qdict;
103
+ Error *local_err = NULL;
104
+ int ret;
105
+
106
+ v = qobject_output_visitor_new(&obj);
107
+ visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err);
108
+ visit_free(v);
109
+
110
+ if (local_err) {
111
+ error_propagate(errp, local_err);
112
+ qobject_decref(obj);
113
+ return -EINVAL;
114
+ }
115
+
116
+ qdict = qobject_to_qdict(obj);
117
+ qdict_flatten(qdict);
118
+
119
+ qdict_put_str(qdict, "driver", "sheepdog");
120
+
121
+ bs = bdrv_open(NULL, NULL, qdict, BDRV_O_PROTOCOL | BDRV_O_RDWR, errp);
122
+ if (bs == NULL) {
123
+ ret = -EIO;
124
+ goto fail;
125
+ }
126
+
127
+ ret = sd_prealloc(bs, 0, size, errp);
128
+fail:
129
+ bdrv_unref(bs);
130
+ QDECREF(qdict);
131
+ return ret;
132
+}
133
+
134
static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
135
{
136
struct SheepdogInode *inode = &s->inode;
137
@@ -XXX,XX +XXX,XX @@ static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
138
* # create a erasure coded vdi with x data strips and y parity strips
139
* -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
140
*/
141
-static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
142
+static SheepdogRedundancy *parse_redundancy_str(const char *opt)
143
{
144
- struct SheepdogRedundancy redundancy;
145
+ SheepdogRedundancy *redundancy;
146
const char *n1, *n2;
147
long copy, parity;
148
char p[10];
149
@@ -XXX,XX +XXX,XX @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
150
n2 = strtok(NULL, ":");
151
152
if (!n1) {
153
- return -EINVAL;
154
+ return NULL;
155
}
156
157
ret = qemu_strtol(n1, NULL, 10, &copy);
158
if (ret < 0) {
159
- return ret;
160
+ return NULL;
161
}
162
163
+ redundancy = g_new0(SheepdogRedundancy, 1);
164
if (!n2) {
165
- redundancy = (SheepdogRedundancy) {
166
+ *redundancy = (SheepdogRedundancy) {
167
.type = SHEEPDOG_REDUNDANCY_TYPE_FULL,
168
.u.full.copies = copy,
169
};
170
} else {
171
ret = qemu_strtol(n2, NULL, 10, &parity);
172
if (ret < 0) {
173
- return ret;
174
+ return NULL;
175
}
176
177
- redundancy = (SheepdogRedundancy) {
178
+ *redundancy = (SheepdogRedundancy) {
179
.type = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
180
.u.erasure_coded = {
181
.data_strips = copy,
182
@@ -XXX,XX +XXX,XX @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
183
};
184
}
185
186
- return parse_redundancy(s, &redundancy);
187
+ return redundancy;
188
}
189
190
-static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
191
+static int parse_block_size_shift(BDRVSheepdogState *s,
192
+ BlockdevCreateOptionsSheepdog *opts)
193
{
194
struct SheepdogInode *inode = &s->inode;
195
uint64_t object_size;
196
int obj_order;
197
198
- object_size = qemu_opt_get_size_del(opt, BLOCK_OPT_OBJECT_SIZE, 0);
199
- if (object_size) {
200
+ if (opts->has_object_size) {
201
+ object_size = opts->object_size;
202
+
203
if ((object_size - 1) & object_size) { /* not a power of 2? */
204
return -EINVAL;
205
}
206
@@ -XXX,XX +XXX,XX @@ static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
207
return 0;
208
}
209
210
-static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
211
- Error **errp)
212
+static int sd_co_create(BlockdevCreateOptions *options, Error **errp)
213
{
214
- Error *err = NULL;
215
+ BlockdevCreateOptionsSheepdog *opts = &options->u.sheepdog;
216
int ret = 0;
217
uint32_t vid = 0;
218
char *backing_file = NULL;
219
char *buf = NULL;
220
BDRVSheepdogState *s;
221
- SheepdogConfig cfg;
222
uint64_t max_vdi_size;
223
bool prealloc = false;
224
225
+ assert(options->driver == BLOCKDEV_DRIVER_SHEEPDOG);
226
+
227
s = g_new0(BDRVSheepdogState, 1);
228
229
- if (strstr(filename, "://")) {
230
- sd_parse_uri(&cfg, filename, &err);
231
- } else {
232
- parse_vdiname(&cfg, filename, &err);
233
- }
234
- if (err) {
235
- error_propagate(errp, err);
236
+ /* Steal SocketAddress from QAPI, set NULL to prevent double free */
237
+ s->addr = opts->location->server;
238
+ opts->location->server = NULL;
239
+
240
+ if (strlen(opts->location->vdi) >= sizeof(s->name)) {
241
+ error_setg(errp, "'vdi' string too long");
242
+ ret = -EINVAL;
243
goto out;
244
}
245
+ pstrcpy(s->name, sizeof(s->name), opts->location->vdi);
246
247
- buf = cfg.port ? g_strdup_printf("%d", cfg.port) : NULL;
248
- s->addr = sd_socket_address(cfg.path, cfg.host, buf);
249
- g_free(buf);
250
- strcpy(s->name, cfg.vdi);
251
- sd_config_done(&cfg);
252
+ s->inode.vdi_size = opts->size;
253
+ backing_file = opts->backing_file;
254
255
- s->inode.vdi_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
256
- BDRV_SECTOR_SIZE);
257
- backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
258
- buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
259
- if (!buf || !strcmp(buf, "off")) {
260
+ if (!opts->has_preallocation) {
261
+ opts->preallocation = PREALLOC_MODE_OFF;
262
+ }
263
+ switch (opts->preallocation) {
264
+ case PREALLOC_MODE_OFF:
265
prealloc = false;
266
- } else if (!strcmp(buf, "full")) {
267
+ break;
268
+ case PREALLOC_MODE_FULL:
269
prealloc = true;
270
- } else {
271
- error_setg(errp, "Invalid preallocation mode: '%s'", buf);
272
+ break;
273
+ default:
274
+ error_setg(errp, "Preallocation mode not supported for Sheepdog");
275
ret = -EINVAL;
276
goto out;
277
}
278
279
- g_free(buf);
280
- buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
281
- if (buf) {
282
- ret = parse_redundancy_str(s, buf);
283
+ if (opts->has_redundancy) {
284
+ ret = parse_redundancy(s, opts->redundancy);
285
if (ret < 0) {
286
- error_setg(errp, "Invalid redundancy mode: '%s'", buf);
287
+ error_setg(errp, "Invalid redundancy mode");
288
goto out;
289
}
290
}
291
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
292
goto out;
293
}
294
295
- if (backing_file) {
296
+ if (opts->has_backing_file) {
297
BlockBackend *blk;
298
BDRVSheepdogState *base;
299
BlockDriver *drv;
300
301
/* Currently, only Sheepdog backing image is supported. */
302
- drv = bdrv_find_protocol(backing_file, true, NULL);
303
+ drv = bdrv_find_protocol(opts->backing_file, true, NULL);
304
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
305
error_setg(errp, "backing_file must be a sheepdog image");
306
ret = -EINVAL;
307
goto out;
308
}
309
310
- blk = blk_new_open(backing_file, NULL, NULL,
311
+ blk = blk_new_open(opts->backing_file, NULL, NULL,
312
BDRV_O_PROTOCOL, errp);
313
if (blk == NULL) {
314
ret = -EIO;
315
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
316
}
317
318
if (prealloc) {
319
- BlockDriverState *bs;
320
- QDict *opts;
321
-
322
- opts = qdict_new();
323
- qdict_put_str(opts, "driver", "sheepdog");
324
- bs = bdrv_open(filename, NULL, opts, BDRV_O_PROTOCOL | BDRV_O_RDWR,
325
- errp);
326
- if (!bs) {
327
- goto out;
328
- }
329
-
330
- ret = sd_prealloc(bs, 0, s->inode.vdi_size, errp);
331
-
332
- bdrv_unref(bs);
333
+ ret = sd_create_prealloc(opts->location, opts->size, errp);
334
}
335
out:
336
g_free(backing_file);
337
g_free(buf);
338
+ g_free(s->addr);
339
g_free(s);
340
return ret;
341
}
342
343
+static int coroutine_fn sd_co_create_opts(const char *filename, QemuOpts *opts,
344
+ Error **errp)
345
+{
346
+ BlockdevCreateOptions *create_options = NULL;
347
+ QDict *qdict, *location_qdict;
348
+ QObject *crumpled;
349
+ Visitor *v;
350
+ const char *redundancy;
351
+ Error *local_err = NULL;
352
+ int ret;
353
+
354
+ redundancy = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
355
+
356
+ qdict = qemu_opts_to_qdict(opts, NULL);
357
+ qdict_put_str(qdict, "driver", "sheepdog");
358
+
359
+ location_qdict = qdict_new();
360
+ qdict_put(qdict, "location", location_qdict);
361
+
362
+ sd_parse_filename(filename, location_qdict, &local_err);
363
+ if (local_err) {
364
+ error_propagate(errp, local_err);
365
+ ret = -EINVAL;
366
+ goto fail;
367
+ }
368
+
369
+ qdict_flatten(qdict);
370
+
371
+ /* Change legacy command line options into QMP ones */
372
+ static const QDictRenames opt_renames[] = {
373
+ { BLOCK_OPT_BACKING_FILE, "backing-file" },
374
+ { BLOCK_OPT_OBJECT_SIZE, "object-size" },
375
+ { NULL, NULL },
376
+ };
377
+
378
+ if (!qdict_rename_keys(qdict, opt_renames, errp)) {
379
+ ret = -EINVAL;
380
+ goto fail;
381
+ }
382
+
383
+ /* Get the QAPI object */
384
+ crumpled = qdict_crumple(qdict, errp);
385
+ if (crumpled == NULL) {
386
+ ret = -EINVAL;
387
+ goto fail;
388
+ }
389
+
390
+ v = qobject_input_visitor_new_keyval(crumpled);
391
+ visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
392
+ visit_free(v);
393
+ qobject_decref(crumpled);
394
+
395
+ if (local_err) {
396
+ error_propagate(errp, local_err);
397
+ ret = -EINVAL;
398
+ goto fail;
399
+ }
400
+
401
+ assert(create_options->driver == BLOCKDEV_DRIVER_SHEEPDOG);
402
+ create_options->u.sheepdog.size =
403
+ ROUND_UP(create_options->u.sheepdog.size, BDRV_SECTOR_SIZE);
404
+
405
+ if (redundancy) {
406
+ create_options->u.sheepdog.has_redundancy = true;
407
+ create_options->u.sheepdog.redundancy =
408
+ parse_redundancy_str(redundancy);
409
+ if (create_options->u.sheepdog.redundancy == NULL) {
410
+ error_setg(errp, "Invalid redundancy mode");
411
+ ret = -EINVAL;
412
+ goto fail;
413
+ }
414
+ }
415
+
416
+ ret = sd_co_create(create_options, errp);
417
+fail:
418
+ qapi_free_BlockdevCreateOptions(create_options);
419
+ QDECREF(qdict);
420
+ return ret;
421
+}
422
+
423
static void sd_close(BlockDriverState *bs)
424
{
425
Error *local_err = NULL;
426
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog = {
427
.bdrv_reopen_commit = sd_reopen_commit,
428
.bdrv_reopen_abort = sd_reopen_abort,
429
.bdrv_close = sd_close,
430
+ .bdrv_co_create = sd_co_create,
431
.bdrv_co_create_opts = sd_co_create_opts,
432
.bdrv_has_zero_init = bdrv_has_zero_init_1,
433
.bdrv_getlength = sd_getlength,
434
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_tcp = {
435
.bdrv_reopen_commit = sd_reopen_commit,
436
.bdrv_reopen_abort = sd_reopen_abort,
437
.bdrv_close = sd_close,
438
+ .bdrv_co_create = sd_co_create,
439
.bdrv_co_create_opts = sd_co_create_opts,
440
.bdrv_has_zero_init = bdrv_has_zero_init_1,
441
.bdrv_getlength = sd_getlength,
442
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_sheepdog_unix = {
443
.bdrv_reopen_commit = sd_reopen_commit,
444
.bdrv_reopen_abort = sd_reopen_abort,
445
.bdrv_close = sd_close,
446
+ .bdrv_co_create = sd_co_create,
447
.bdrv_co_create_opts = sd_co_create_opts,
448
.bdrv_has_zero_init = bdrv_has_zero_init_1,
449
.bdrv_getlength = sd_getlength,
450
--
451
2.13.6
452
453
diff view generated by jsdifflib
Deleted patch
1
This adds the .bdrv_co_create driver callback to ssh, which enables
2
image creation over QMP.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
---
7
qapi/block-core.json | 16 +++++++++-
8
block/ssh.c | 83 ++++++++++++++++++++++++++++++----------------------
9
2 files changed, 63 insertions(+), 36 deletions(-)
10
11
diff --git a/qapi/block-core.json b/qapi/block-core.json
12
index XXXXXXX..XXXXXXX 100644
13
--- a/qapi/block-core.json
14
+++ b/qapi/block-core.json
15
@@ -XXX,XX +XXX,XX @@
16
'*object-size': 'size' } }
17
18
##
19
+# @BlockdevCreateOptionsSsh:
20
+#
21
+# Driver specific image creation options for SSH.
22
+#
23
+# @location Where to store the new image file
24
+# @size Size of the virtual disk in bytes
25
+#
26
+# Since: 2.12
27
+##
28
+{ 'struct': 'BlockdevCreateOptionsSsh',
29
+ 'data': { 'location': 'BlockdevOptionsSsh',
30
+ 'size': 'size' } }
31
+
32
+##
33
# @BlockdevCreateNotSupported:
34
#
35
# This is used for all drivers that don't support creating images.
36
@@ -XXX,XX +XXX,XX @@
37
'rbd': 'BlockdevCreateOptionsRbd',
38
'replication': 'BlockdevCreateNotSupported',
39
'sheepdog': 'BlockdevCreateOptionsSheepdog',
40
- 'ssh': 'BlockdevCreateNotSupported',
41
+ 'ssh': 'BlockdevCreateOptionsSsh',
42
'throttle': 'BlockdevCreateNotSupported',
43
'vdi': 'BlockdevCreateNotSupported',
44
'vhdx': 'BlockdevCreateNotSupported',
45
diff --git a/block/ssh.c b/block/ssh.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/ssh.c
48
+++ b/block/ssh.c
49
@@ -XXX,XX +XXX,XX @@ static QemuOptsList ssh_create_opts = {
50
}
51
};
52
53
+static int ssh_co_create(BlockdevCreateOptions *options, Error **errp)
54
+{
55
+ BlockdevCreateOptionsSsh *opts = &options->u.ssh;
56
+ BDRVSSHState s;
57
+ int ret;
58
+
59
+ assert(options->driver == BLOCKDEV_DRIVER_SSH);
60
+
61
+ ssh_state_init(&s);
62
+
63
+ ret = connect_to_ssh(&s, opts->location,
64
+ LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
65
+ LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
66
+ 0644, errp);
67
+ if (ret < 0) {
68
+ goto fail;
69
+ }
70
+
71
+ if (opts->size > 0) {
72
+ ret = ssh_grow_file(&s, opts->size, errp);
73
+ if (ret < 0) {
74
+ goto fail;
75
+ }
76
+ }
77
+
78
+ ret = 0;
79
+fail:
80
+ ssh_state_free(&s);
81
+ return ret;
82
+}
83
+
84
static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts,
85
Error **errp)
86
{
87
- int r, ret;
88
- int64_t total_size = 0;
89
+ BlockdevCreateOptions *create_options;
90
+ BlockdevCreateOptionsSsh *ssh_opts;
91
+ int ret;
92
QDict *uri_options = NULL;
93
- BlockdevOptionsSsh *ssh_opts = NULL;
94
- BDRVSSHState s;
95
96
- ssh_state_init(&s);
97
+ create_options = g_new0(BlockdevCreateOptions, 1);
98
+ create_options->driver = BLOCKDEV_DRIVER_SSH;
99
+ ssh_opts = &create_options->u.ssh;
100
101
/* Get desired file size. */
102
- total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
103
- BDRV_SECTOR_SIZE);
104
- DPRINTF("total_size=%" PRIi64, total_size);
105
+ ssh_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
106
+ BDRV_SECTOR_SIZE);
107
+ DPRINTF("total_size=%" PRIi64, ssh_opts->size);
108
109
uri_options = qdict_new();
110
- r = parse_uri(filename, uri_options, errp);
111
- if (r < 0) {
112
- ret = r;
113
+ ret = parse_uri(filename, uri_options, errp);
114
+ if (ret < 0) {
115
goto out;
116
}
117
118
- ssh_opts = ssh_parse_options(uri_options, errp);
119
- if (ssh_opts == NULL) {
120
+ ssh_opts->location = ssh_parse_options(uri_options, errp);
121
+ if (ssh_opts->location == NULL) {
122
ret = -EINVAL;
123
goto out;
124
}
125
126
- r = connect_to_ssh(&s, ssh_opts,
127
- LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|
128
- LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
129
- 0644, errp);
130
- if (r < 0) {
131
- ret = r;
132
- goto out;
133
- }
134
-
135
- if (total_size > 0) {
136
- ret = ssh_grow_file(&s, total_size, errp);
137
- if (ret < 0) {
138
- goto out;
139
- }
140
- }
141
-
142
- ret = 0;
143
+ ret = ssh_co_create(create_options, errp);
144
145
out:
146
- ssh_state_free(&s);
147
- if (uri_options != NULL) {
148
- QDECREF(uri_options);
149
- }
150
- qapi_free_BlockdevOptionsSsh(ssh_opts);
151
+ QDECREF(uri_options);
152
+ qapi_free_BlockdevCreateOptions(create_options);
153
return ret;
154
}
155
156
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_ssh = {
157
.instance_size = sizeof(BDRVSSHState),
158
.bdrv_parse_filename = ssh_parse_filename,
159
.bdrv_file_open = ssh_file_open,
160
+ .bdrv_co_create = ssh_co_create,
161
.bdrv_co_create_opts = ssh_co_create_opts,
162
.bdrv_close = ssh_close,
163
.bdrv_has_zero_init = ssh_has_zero_init,
164
--
165
2.13.6
166
167
diff view generated by jsdifflib
Deleted patch
1
From: Fam Zheng <famz@redhat.com>
2
1
3
Signed-off-by: Fam Zheng <famz@redhat.com>
4
Message-id: 20171225025107.23985-1-famz@redhat.com
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/153 | 8 +++++---
9
tests/qemu-iotests/153.out | 7 ++++---
10
2 files changed, 9 insertions(+), 6 deletions(-)
11
12
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/153
15
+++ b/tests/qemu-iotests/153
16
@@ -XXX,XX +XXX,XX @@ _cleanup()
17
{
18
_cleanup_test_img
19
rm -f "${TEST_IMG}.base"
20
+ rm -f "${TEST_IMG}.overlay"
21
rm -f "${TEST_IMG}.convert"
22
rm -f "${TEST_IMG}.a"
23
rm -f "${TEST_IMG}.b"
24
@@ -XXX,XX +XXX,XX @@ rm -f "${TEST_IMG}.lnk" &>/dev/null
25
ln -s ${TEST_IMG} "${TEST_IMG}.lnk" || echo "Failed to create link"
26
_run_qemu_with_images "${TEST_IMG}.lnk" "${TEST_IMG}"
27
28
-echo
29
-echo "== Closing an image should unlock it =="
30
_launch_qemu
31
32
_send_qemu_cmd $QEMU_HANDLE \
33
@@ -XXX,XX +XXX,XX @@ _send_qemu_cmd $QEMU_HANDLE \
34
35
_run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
36
37
-echo "Closing drive"
38
+echo "Creating overlay with qemu-img when the guest is running should be allowed"
39
+_run_cmd $QEMU_IMG create -f $IMGFMT -b "${TEST_IMG}" "${TEST_IMG}.overlay"
40
+
41
+echo "== Closing an image should unlock it =="
42
_send_qemu_cmd $QEMU_HANDLE \
43
"{ 'execute': 'human-monitor-command',
44
'arguments': { 'command-line': 'drive_del d0' } }" \
45
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
46
index XXXXXXX..XXXXXXX 100644
47
--- a/tests/qemu-iotests/153.out
48
+++ b/tests/qemu-iotests/153.out
49
@@ -XXX,XX +XXX,XX @@ Is another process using the image?
50
== Symbolic link ==
51
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
52
Is another process using the image?
53
-
54
-== Closing an image should unlock it ==
55
{"return": {}}
56
Adding drive
57
58
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
59
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
60
Is another process using the image?
61
-Closing drive
62
+Creating overlay with qemu-img when the guest is running should be allowed
63
+
64
+_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
65
+== Closing an image should unlock it ==
66
67
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
68
Adding two and closing one
69
--
70
2.13.6
71
72
diff view generated by jsdifflib