1
The following changes since commit ee86981bda9ecd40c8daf81b7307b1d2aff68174:
1
The following changes since commit f4c4357fbfca0fb14e477bf661ae7384b4b9b283:
2
2
3
migration: Revert postcopy-blocktime commit set (2018-01-23 10:08:05 +0000)
3
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-docs-20200306' into staging (2020-03-06 11:11:54 +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 8c0c5e636e6b11eaf0556be31fceb68e0baff310:
9
for you to fetch changes up to 1de6b45fb5c1489b450df7d1a4c692bba9678ce6:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-01-23' into queue-block (2018-01-23 12:40:46 +0100)
11
block: bdrv_reopen() with backing file in different AioContext (2020-03-06 17:34:09 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches
14
Block layer patches:
15
16
- Add qemu-storage-daemon (still experimental)
17
- rbd: Add support for ceph namespaces
18
- Fix bdrv_reopen() with backing file in different AioContext
19
- qcow2: Fix read-write reopen with persistent dirty bitmaps
20
- qcow2: Fix alloc_cluster_abort() for pre-existing clusters
15
21
16
----------------------------------------------------------------
22
----------------------------------------------------------------
17
Daniel Henrique Barboza (1):
23
Florian Florensa (1):
18
tests/qemu-iotests: adding savevm/loadvm with postcopy flag test
24
block/rbd: Add support for ceph namespaces
19
25
20
Eric Blake (1):
26
Kevin Wolf (22):
21
iotests: Split 177 into two parts for compat=0.10
27
qemu-storage-daemon: Add barebone tool
28
stubs: Add arch_type
29
block: Move system emulator QMP commands to block/qapi-sysemu.c
30
block: Move common QMP commands to block-core QAPI module
31
block: Move sysemu QMP commands to QAPI block module
32
qemu-storage-daemon: Add --blockdev option
33
qapi: Flatten object-add
34
qemu-storage-daemon: Add --object option
35
qemu-storage-daemon: Add --nbd-server option
36
blockdev-nbd: Boxed argument type for nbd-server-add
37
qemu-storage-daemon: Add --export option
38
qemu-storage-daemon: Add main loop
39
qemu-storage-daemon: Add --chardev option
40
stubs: Update monitor stubs for qemu-storage-daemon
41
qapi: Create 'pragma' module
42
monitor: Create QAPIfied monitor_init()
43
qmp: Fail gracefully if chardev is already in use
44
hmp: Fail gracefully if chardev is already in use
45
monitor: Add allow_hmp parameter to monitor_init()
46
qemu-storage-daemon: Add --monitor option
47
iotests: Refactor blockdev-reopen test for iothreads
48
block: bdrv_reopen() with backing file in different AioContext
22
49
23
Fam Zheng (1):
50
Max Reitz (4):
24
osdep: Retry SETLK upon EINTR
51
qcow2: Fix alloc_cluster_abort() for pre-existing clusters
52
iotests/026: Test EIO on preallocated zero cluster
53
iotests/026: Test EIO on allocation in a data-file
54
block: Fix leak in bdrv_create_file_fallback()
25
55
26
Hikaru Nishida (1):
56
Peter Krempa (2):
27
hw/block: Fix pin-based interrupt behaviour of NVMe
57
block: Introduce 'bdrv_reopen_commit_post' step
58
block/qcow2: Move bitmap reopen into bdrv_reopen_commit_post
28
59
29
Kevin Wolf (2):
60
qapi/block-core.json | 733 +++++++++++++++++------------------
30
tests/.gitignore: Add test-bdrv-drain
61
qapi/block.json | 512 ++++++++++++++----------
31
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-01-23' into queue-block
62
qapi/control.json | 37 ++
63
qapi/pragma.json | 24 ++
64
qapi/qapi-schema.json | 25 +-
65
qapi/qom.json | 12 +-
66
qapi/transaction.json | 2 +-
67
docs/system/deprecated.rst | 5 +
68
configure | 2 +-
69
include/block/block_int.h | 1 +
70
include/block/nbd.h | 1 +
71
include/monitor/monitor.h | 6 +-
72
include/qom/object_interfaces.h | 7 +
73
include/sysemu/arch_init.h | 2 +
74
block.c | 44 ++-
75
block/qapi-sysemu.c | 590 ++++++++++++++++++++++++++++
76
block/qcow2-cluster.c | 2 +-
77
block/qcow2.c | 7 +-
78
block/rbd.c | 44 ++-
79
blockdev-nbd.c | 40 +-
80
blockdev.c | 559 --------------------------
81
chardev/char.c | 8 +-
82
gdbstub.c | 2 +-
83
hw/block/xen-block.c | 11 +-
84
monitor/hmp-cmds.c | 21 +-
85
monitor/hmp.c | 8 +-
86
monitor/misc.c | 2 +
87
monitor/monitor.c | 86 ++--
88
monitor/qmp-cmds.c | 2 +-
89
monitor/qmp.c | 11 +-
90
qemu-storage-daemon.c | 340 ++++++++++++++++
91
qom/qom-qmp-cmds.c | 42 +-
92
stubs/arch_type.c | 4 +
93
stubs/monitor-core.c | 21 +
94
stubs/monitor.c | 17 +-
95
tests/test-util-sockets.c | 4 +-
96
scripts/qapi/gen.py | 5 +
97
Makefile | 37 ++
98
Makefile.objs | 9 +
99
block/Makefile.objs | 4 +-
100
monitor/Makefile.objs | 2 +
101
qapi/Makefile.objs | 7 +-
102
qom/Makefile.objs | 1 +
103
storage-daemon/Makefile.objs | 1 +
104
storage-daemon/qapi/Makefile.objs | 1 +
105
storage-daemon/qapi/qapi-schema.json | 26 ++
106
stubs/Makefile.objs | 2 +
107
tests/qemu-iotests/026 | 53 +++
108
tests/qemu-iotests/026.out | 16 +
109
tests/qemu-iotests/026.out.nocache | 16 +
110
tests/qemu-iotests/245 | 45 ++-
111
tests/qemu-iotests/245.out | 4 +-
112
52 files changed, 2157 insertions(+), 1306 deletions(-)
113
create mode 100644 qapi/pragma.json
114
create mode 100644 block/qapi-sysemu.c
115
create mode 100644 qemu-storage-daemon.c
116
create mode 100644 stubs/arch_type.c
117
create mode 100644 stubs/monitor-core.c
118
create mode 100644 storage-daemon/Makefile.objs
119
create mode 100644 storage-daemon/qapi/Makefile.objs
120
create mode 100644 storage-daemon/qapi/qapi-schema.json
32
121
33
Max Reitz (24):
34
qcow2: Repair unaligned preallocated zero clusters
35
iotests: Make BD-{remove,insert}-medium use @id
36
tests/ahci: Switch tray and medium commands to @id
37
blockdev: Drop BD-{remove,insert}-medium's @device
38
blockdev: Mark BD-{remove,insert}-medium stable
39
qemu-iotests: Fix locking issue in 102
40
block/vmdk: Fix , instead of ; at end of line
41
qcow2: No persistent dirty bitmaps for compat=0.10
42
block/qcow: Add blkdebug events
43
block/vmdk: Add blkdebug events
44
iotests: Fix _img_info for backslashes
45
iotests: Drop format-specific in _filter_img_info
46
iotests: Forbid 020 for non-file protocols
47
iotests: Skip 103 for refcount_bits=1
48
iotests: Fix 020 for vmdk
49
iotests: Fix 051 for compat=0.10
50
iotests: Fix 059's reference output
51
iotests: Fix 067 for compat=0.10
52
iotests: Make 089 compatible with compat=0.10
53
iotests: Make 184 image-less
54
iotests: Make 191 work with qcow2 options
55
iotests: Filter compat-dependent info in 198
56
iotests: Make 059 pass on machines with little RAM
57
iotests: Disable some tests for compat=0.10
58
122
59
qapi/block-core.json | 42 ++----
60
hw/block/nvme.h | 1 +
61
block/qcow.c | 16 ++
62
block/qcow2-bitmap.c | 10 ++
63
block/qcow2-refcount.c | 70 +++++++--
64
block/qcow2.c | 14 +-
65
block/vmdk.c | 18 ++-
66
blockdev.c | 30 +++-
67
hw/block/nvme.c | 39 ++++-
68
tests/ahci-test.c | 16 +-
69
util/osdep.c | 4 +-
70
tests/.gitignore | 1 +
71
tests/qemu-iotests/020 | 17 +--
72
tests/qemu-iotests/020.out | 6 +-
73
tests/qemu-iotests/051 | 2 +
74
tests/qemu-iotests/051.out | 1 +
75
tests/qemu-iotests/051.pc.out | 1 +
76
tests/qemu-iotests/059 | 4 +-
77
tests/qemu-iotests/059.out | 2 +-
78
tests/qemu-iotests/060 | 3 +-
79
tests/qemu-iotests/060.out | 9 ++
80
tests/qemu-iotests/067 | 3 +-
81
tests/qemu-iotests/067.out | 97 ++++--------
82
tests/qemu-iotests/080 | 5 +-
83
tests/qemu-iotests/089 | 4 +-
84
tests/qemu-iotests/089.out | 10 --
85
tests/qemu-iotests/093 | 6 +-
86
tests/qemu-iotests/102 | 7 +-
87
tests/qemu-iotests/102.out | 3 +-
88
tests/qemu-iotests/103 | 2 +
89
tests/qemu-iotests/118 | 184 +++++++++++------------
90
tests/qemu-iotests/130 | 2 +
91
tests/qemu-iotests/137 | 2 +
92
tests/qemu-iotests/139 | 2 +-
93
tests/qemu-iotests/155 | 60 ++++----
94
tests/qemu-iotests/176 | 2 +
95
tests/qemu-iotests/177 | 20 +--
96
tests/qemu-iotests/177.out | 22 +--
97
tests/qemu-iotests/184 | 25 +---
98
tests/qemu-iotests/184.out | 63 ++------
99
tests/qemu-iotests/191 | 5 +-
100
tests/qemu-iotests/191.out | 313 +++++++++++----------------------------
101
tests/qemu-iotests/198 | 8 +-
102
tests/qemu-iotests/198.out | 8 -
103
tests/qemu-iotests/201 | 120 +++++++++++++++
104
tests/qemu-iotests/201.out | 23 +++
105
tests/qemu-iotests/204 | 119 +++++++++++++++
106
tests/qemu-iotests/204.out | 63 ++++++++
107
tests/qemu-iotests/common.filter | 29 +++-
108
tests/qemu-iotests/common.rc | 2 +-
109
tests/qemu-iotests/group | 2 +
110
51 files changed, 870 insertions(+), 647 deletions(-)
111
create mode 100755 tests/qemu-iotests/201
112
create mode 100644 tests/qemu-iotests/201.out
113
create mode 100755 tests/qemu-iotests/204
114
create mode 100644 tests/qemu-iotests/204.out
115
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
As of commit 9877860e7bd1e26ee70ab9bb5ebc34c92bf23bf5, vmdk fails
3
handle_alloc() reuses preallocated zero clusters. If anything goes
4
differently when opening the sample image.
4
wrong during the data write, we do not change their L2 entry, so we
5
must not let qcow2_alloc_cluster_abort() free them.
5
6
7
Fixes: 8b24cd141549b5b264baeddd4e72902cfb5de23b
8
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20171123020832.8165-13-mreitz@redhat.com
10
Message-Id: <20200225143130.111267-2-mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
---
12
tests/qemu-iotests/059.out | 2 +-
13
block/qcow2-cluster.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
15
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/059.out
18
--- a/block/qcow2-cluster.c
18
+++ b/tests/qemu-iotests/059.out
19
+++ b/block/qcow2-cluster.c
19
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
20
@@ -XXX,XX +XXX,XX @@ err:
20
0x140000000 0x10000 0x50000 TEST_DIR/t-s003.vmdk
21
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
21
22
{
22
=== Testing afl image with a very large capacity ===
23
BDRVQcow2State *s = bs->opaque;
23
-qemu-img: Can't get image size 'TEST_DIR/afl9.IMGFMT': File too large
24
- if (!has_data_file(bs)) {
24
+qemu-img: Could not open 'TEST_DIR/afl9.IMGFMT': Could not open 'TEST_DIR/afl9.IMGFMT': Invalid argument
25
+ if (!has_data_file(bs) && !m->keep_old_clusters) {
25
*** done
26
qcow2_free_clusters(bs, m->alloc_offset,
27
m->nb_clusters << s->cluster_bits,
28
QCOW2_DISCARD_NEVER);
26
--
29
--
27
2.13.6
30
2.20.1
28
31
29
32
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
There is a bit of image-specific information which depends on the qcow2
3
Test what happens when writing data to a preallocated zero cluster, but
4
compat level. Filter it so that 198 works with compat=0.10 (and any
4
the data write fails.
5
refcount_bits value).
6
7
Note that we cannot simply drop the --format-specific switch because we
8
do need the "encrypt" information.
9
5
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Message-id: 20171123020832.8165-18-mreitz@redhat.com
7
Message-Id: <20200225143130.111267-3-mreitz@redhat.com>
12
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
9
---
15
tests/qemu-iotests/198 | 6 ++++--
10
tests/qemu-iotests/026 | 21 +++++++++++++++++++++
16
tests/qemu-iotests/198.out | 8 --------
11
tests/qemu-iotests/026.out | 10 ++++++++++
17
2 files changed, 4 insertions(+), 10 deletions(-)
12
tests/qemu-iotests/026.out.nocache | 10 ++++++++++
13
3 files changed, 41 insertions(+)
18
14
19
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
15
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
20
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/198
17
--- a/tests/qemu-iotests/026
22
+++ b/tests/qemu-iotests/198
18
+++ b/tests/qemu-iotests/026
23
@@ -XXX,XX +XXX,XX @@ $QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0x9 0 $size" --image-op
19
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
24
echo
20
$QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
25
echo "== checking image base =="
21
_check_test_img
26
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
22
27
- | sed -e "/^disk size:/ D"
23
+echo
28
+ | sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
24
+echo === Avoid freeing preallocated zero clusters on failure ===
29
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
25
+echo
30
26
+
31
echo
27
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
32
echo "== checking image layer =="
28
+[inject-error]
33
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
29
+event = "write_aio"
34
- | sed -e "/^disk size:/ D"
30
+errno = "5"
35
+ | sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
31
+once = "on"
36
+ -e '/lazy refcounts:/ D' -e '/corrupt:/ D'
32
+EOF
37
33
+
38
34
+_make_test_img $CLUSTER_SIZE
35
+# Create a preallocated zero cluster
36
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" -c "write -z 0 $CLUSTER_SIZE" "$TEST_IMG" \
37
+ | _filter_qemu_io
38
+# Try to overwrite it (prompting an I/O error from blkdebug), thus
39
+# triggering the alloc abort code
40
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io
41
+
42
+_check_test_img
43
+
39
# success, all done
44
# success, all done
40
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
45
echo "*** done"
46
rm -f $seq.full
47
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
41
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/198.out
49
--- a/tests/qemu-iotests/026.out
43
+++ b/tests/qemu-iotests/198.out
50
+++ b/tests/qemu-iotests/026.out
44
@@ -XXX,XX +XXX,XX @@ image: json:{"encrypt.key-secret": "sec0", "driver": "IMGFMT", "file": {"driver"
51
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
45
file format: IMGFMT
52
wrote 1048576/1048576 bytes at offset 0
46
virtual size: 16M (16777216 bytes)
53
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
47
Format specific information:
54
No errors were found on the image.
48
- compat: 1.1
55
+
49
- lazy refcounts: false
56
+=== Avoid freeing preallocated zero clusters on failure ===
50
- refcount bits: 16
57
+
51
encrypt:
58
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
52
ivgen alg: plain64
59
+wrote 1024/1024 bytes at offset 0
53
hash alg: sha256
60
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
54
@@ -XXX,XX +XXX,XX @@ Format specific information:
61
+wrote 1024/1024 bytes at offset 0
55
key offset: 1810432
62
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
56
payload offset: 2068480
63
+write failed: Input/output error
57
master key iters: 1024
64
+No errors were found on the image.
58
- corrupt: false
65
*** done
59
66
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
60
== checking image layer ==
67
index XXXXXXX..XXXXXXX 100644
61
image: json:{"encrypt.key-secret": "sec1", "driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}}
68
--- a/tests/qemu-iotests/026.out.nocache
62
@@ -XXX,XX +XXX,XX @@ file format: IMGFMT
69
+++ b/tests/qemu-iotests/026.out.nocache
63
virtual size: 16M (16777216 bytes)
70
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
64
backing file: TEST_DIR/t.IMGFMT.base
71
wrote 1048576/1048576 bytes at offset 0
65
Format specific information:
72
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
66
- compat: 1.1
73
No errors were found on the image.
67
- lazy refcounts: false
74
+
68
- refcount bits: 16
75
+=== Avoid freeing preallocated zero clusters on failure ===
69
encrypt:
76
+
70
ivgen alg: plain64
77
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
71
hash alg: sha256
78
+wrote 1024/1024 bytes at offset 0
72
@@ -XXX,XX +XXX,XX @@ Format specific information:
79
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
key offset: 1810432
80
+wrote 1024/1024 bytes at offset 0
74
payload offset: 2068480
81
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
master key iters: 1024
82
+write failed: Input/output error
76
- corrupt: false
83
+No errors were found on the image.
77
*** done
84
*** done
78
--
85
--
79
2.13.6
86
2.20.1
80
87
81
88
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
The only thing that is missing is a _filter_img_info after the
3
Test what happens when writing data to an external data file, where the
4
"$QEMU_IO -c info" invocations.
4
write requires an L2 entry to be allocated, but the data write fails.
5
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20171123020832.8165-15-mreitz@redhat.com
7
Message-Id: <20200225143130.111267-4-mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
9
---
11
tests/qemu-iotests/089 | 4 ++--
10
tests/qemu-iotests/026 | 32 ++++++++++++++++++++++++++++++
12
tests/qemu-iotests/089.out | 10 ----------
11
tests/qemu-iotests/026.out | 6 ++++++
13
2 files changed, 2 insertions(+), 12 deletions(-)
12
tests/qemu-iotests/026.out.nocache | 6 ++++++
13
3 files changed, 44 insertions(+)
14
14
15
diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089
15
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
16
index XXXXXXX..XXXXXXX 100755
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/089
17
--- a/tests/qemu-iotests/026
18
+++ b/tests/qemu-iotests/089
18
+++ b/tests/qemu-iotests/026
19
@@ -XXX,XX +XXX,XX @@ echo
19
@@ -XXX,XX +XXX,XX @@ _cleanup()
20
20
{
21
# Both options given directly and those given in the filename should be used
21
    _cleanup_test_img
22
$QEMU_IO -c "open -o driver=qcow2 json:{\"file.filename\":\"$TEST_IMG\"}" \
22
rm "$TEST_DIR/blkdebug.conf"
23
- -c "info" 2>&1 | _filter_testdir | _filter_imgfmt
23
+ rm -f "$TEST_IMG.data_file"
24
+ -c "info" 2>&1 | _filter_img_info
24
}
25
25
trap "_cleanup; exit \$status" 0 1 2 3 15
26
# Options given directly should be prioritized over those given in the filename
26
27
$QEMU_IO -c "open -o driver=qcow2 json:{\"driver\":\"raw\",\"file.filename\":\"$TEST_IMG\"}" \
27
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io
28
- -c "info" 2>&1 | _filter_testdir | _filter_imgfmt
28
29
+ -c "info" 2>&1 | _filter_img_info
29
_check_test_img
30
30
31
31
+echo
32
+echo === Avoid freeing external data clusters on failure ===
33
+echo
34
+
35
+# Similar test as the last one, except we test what happens when there
36
+# is an error when writing to an external data file instead of when
37
+# writing to a preallocated zero cluster
38
+_make_test_img -o "data_file=$TEST_IMG.data_file" $CLUSTER_SIZE
39
+
40
+# Put blkdebug above the data-file, and a raw node on top of that so
41
+# that blkdebug will see a write_aio event and emit an error
42
+$QEMU_IO -c "write 0 $CLUSTER_SIZE" \
43
+ "json:{
44
+ 'driver': 'qcow2',
45
+ 'file': { 'driver': 'file', 'filename': '$TEST_IMG' },
46
+ 'data-file': {
47
+ 'driver': 'raw',
48
+ 'file': {
49
+ 'driver': 'blkdebug',
50
+ 'config': '$TEST_DIR/blkdebug.conf',
51
+ 'image': {
52
+ 'driver': 'file',
53
+ 'filename': '$TEST_IMG.data_file'
54
+ }
55
+ }
56
+ }
57
+ }" \
58
+ | _filter_qemu_io
59
+
60
+_check_test_img
61
+
32
# success, all done
62
# success, all done
33
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
63
echo "*** done"
64
rm -f $seq.full
65
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
34
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
35
--- a/tests/qemu-iotests/089.out
67
--- a/tests/qemu-iotests/026.out
36
+++ b/tests/qemu-iotests/089.out
68
+++ b/tests/qemu-iotests/026.out
37
@@ -XXX,XX +XXX,XX @@ cluster_size: 65536
69
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 0
38
format name: IMGFMT
70
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
39
cluster size: 64 KiB
71
write failed: Input/output error
40
vm state offset: 512 MiB
72
No errors were found on the image.
41
-Format specific information:
73
+
42
- compat: 1.1
74
+=== Avoid freeing external data clusters on failure ===
43
- lazy refcounts: false
75
+
44
- refcount bits: 16
76
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file
45
- corrupt: false
77
+write failed: Input/output error
46
format name: IMGFMT
78
+No errors were found on the image.
47
cluster size: 64 KiB
79
*** done
48
vm state offset: 512 MiB
80
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
49
-Format specific information:
81
index XXXXXXX..XXXXXXX 100644
50
- compat: 1.1
82
--- a/tests/qemu-iotests/026.out.nocache
51
- lazy refcounts: false
83
+++ b/tests/qemu-iotests/026.out.nocache
52
- refcount bits: 16
84
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 0
53
- corrupt: false
85
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
86
write failed: Input/output error
87
No errors were found on the image.
88
+
89
+=== Avoid freeing external data clusters on failure ===
90
+
91
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file
92
+write failed: Input/output error
93
+No errors were found on the image.
54
*** done
94
*** done
55
--
95
--
56
2.13.6
96
2.20.1
57
97
58
98
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Max Reitz <mreitz@redhat.com>
2
2
3
read without -r eats backslashes.
3
@options is leaked by the first two return statements in this function.
4
4
5
Note that blk_new_open() takes the reference to @options even on
6
failure, so all we need to do to fix the leak is to move the QDict
7
allocation down to where we actually need it.
8
9
Reported-by: Coverity (CID 1419884)
10
Fixes: fd17146cd93d1704cd96d7c2757b325fc7aac6fd
11
("block: Generic file creation fallback")
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Message-id: 20171123020832.8165-6-mreitz@redhat.com
13
Message-Id: <20200225155618.133412-1-mreitz@redhat.com>
7
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
15
---
10
tests/qemu-iotests/common.rc | 2 +-
16
block.c | 3 ++-
11
1 file changed, 1 insertion(+), 1 deletion(-)
17
1 file changed, 2 insertions(+), 1 deletion(-)
12
18
13
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
19
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/qemu-iotests/common.rc
21
--- a/block.c
16
+++ b/tests/qemu-iotests/common.rc
22
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ _img_info()
23
@@ -XXX,XX +XXX,XX @@ static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv,
18
-e "s#$IMGFMT#IMGFMT#g" \
24
QemuOpts *opts, Error **errp)
19
-e "/^disk size:/ D" \
25
{
20
-e "/actual-size/ D" | \
26
BlockBackend *blk;
21
- while IFS='' read line; do
27
- QDict *options = qdict_new();
22
+ while IFS='' read -r line; do
28
+ QDict *options;
23
if [[ $format_specific == 1 ]]; then
29
int64_t size = 0;
24
discard=0
30
char *buf = NULL;
25
elif [[ $line == "Format specific information:" ]]; then
31
PreallocMode prealloc;
32
@@ -XXX,XX +XXX,XX @@ static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv,
33
return -ENOTSUP;
34
}
35
36
+ options = qdict_new();
37
qdict_put_str(options, "driver", drv->format_name);
38
39
blk = blk_new_open(filename, NULL, options,
26
--
40
--
27
2.13.6
41
2.20.1
28
42
29
43
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Peter Krempa <pkrempa@redhat.com>
2
2
3
Tests 080, 130, 137, and 176 simply do not work with compat=0.10 for the
3
Add another step in the reopen process where driver can execute code
4
reasons stated there.
4
after permission changes are comitted.
5
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
7
Message-Id: <20171123020832.8165-10-mreitz@redhat.com>
7
Message-Id: <adc02cf591c3cb34e98e33518eb1c540a0f27db1.1582893284.git.pkrempa@redhat.com>
8
[eblake: fix 177 in a separate commit]
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Message-id: 20180117165420.15946-3-eblake@redhat.com
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
9
---
13
tests/qemu-iotests/080 | 5 +++--
10
include/block/block_int.h | 1 +
14
tests/qemu-iotests/130 | 2 ++
11
block.c | 9 +++++++++
15
tests/qemu-iotests/137 | 2 ++
12
2 files changed, 10 insertions(+)
16
tests/qemu-iotests/176 | 2 ++
17
4 files changed, 9 insertions(+), 2 deletions(-)
18
13
19
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
20
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
21
--- a/tests/qemu-iotests/080
16
--- a/include/block/block_int.h
22
+++ b/tests/qemu-iotests/080
17
+++ b/include/block/block_int.h
23
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
24
_supported_fmt qcow2
19
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
25
_supported_proto file
20
BlockReopenQueue *queue, Error **errp);
26
_supported_os Linux
21
void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
27
-# Internal snapshots are (currently) impossible with refcount_bits=1
22
+ void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state);
28
-_unsupported_imgopts 'refcount_bits=1[^0-9]'
23
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
29
+# - Internal snapshots are (currently) impossible with refcount_bits=1
24
void (*bdrv_join_options)(QDict *options, QDict *old_options);
30
+# - This is generally a test for compat=1.1 images
25
31
+_unsupported_imgopts 'refcount_bits=1[^0-9]' 'compat=0.10'
26
diff --git a/block.c b/block.c
32
27
index XXXXXXX..XXXXXXX 100644
33
header_size=104
28
--- a/block.c
34
29
+++ b/block.c
35
diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130
30
@@ -XXX,XX +XXX,XX @@ cleanup_perm:
36
index XXXXXXX..XXXXXXX 100755
31
}
37
--- a/tests/qemu-iotests/130
32
}
38
+++ b/tests/qemu-iotests/130
33
}
39
@@ -XXX,XX +XXX,XX @@ _supported_fmt qcow2
34
+
40
_supported_proto generic
35
+ if (ret == 0) {
41
_unsupported_proto vxhs
36
+ QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
42
_supported_os Linux
37
+ BlockDriverState *bs = bs_entry->state.bs;
43
+# We are going to use lazy-refcounts
38
+
44
+_unsupported_imgopts 'compat=0.10'
39
+ if (bs->drv->bdrv_reopen_commit_post)
45
40
+ bs->drv->bdrv_reopen_commit_post(&bs_entry->state);
46
qemu_comm_method="monitor"
41
+ }
47
42
+ }
48
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
43
cleanup:
49
index XXXXXXX..XXXXXXX 100755
44
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
50
--- a/tests/qemu-iotests/137
45
if (ret) {
51
+++ b/tests/qemu-iotests/137
52
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
53
_supported_fmt qcow2
54
_supported_proto file
55
_supported_os Linux
56
+# We are going to use lazy-refcounts
57
+_unsupported_imgopts 'compat=0.10'
58
59
60
_make_test_img 64M
61
diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176
62
index XXXXXXX..XXXXXXX 100755
63
--- a/tests/qemu-iotests/176
64
+++ b/tests/qemu-iotests/176
65
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
66
_supported_fmt qcow2
67
_supported_proto file
68
_supported_os Linux
69
+# Persistent dirty bitmaps require compat=1.1
70
+_unsupported_imgopts 'compat=0.10'
71
72
function run_qemu()
73
{
74
--
46
--
75
2.13.6
47
2.20.1
76
48
77
49
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Peter Krempa <pkrempa@redhat.com>
2
2
3
Persistent dirty bitmaps require a properly functioning
3
The bitmap code requires writing the 'file' child when the qcow2 driver
4
autoclear_features field, or we cannot track when an unsupporting
4
is reopened in read-write mode.
5
program might overwrite them. Therefore, we cannot support them for
6
compat=0.10 images.
7
5
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
6
If the 'file' child is being reopened due to a permissions change, the
9
Message-id: 20171123020832.8165-3-mreitz@redhat.com
7
modification is commited yet when qcow2_reopen_commit is called. This
10
Reviewed-by: Eric Blake <eblake@redhat.com>
8
means that any attempt to write the 'file' child will end with EBADFD
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
as the original fd was already closed.
10
11
Moving bitmap reopening to the new callback which is called after
12
permission modifications are commited fixes this as the file descriptor
13
will be replaced with the correct one.
14
15
The above problem manifests itself when reopening 'qcow2' format layer
16
which uses a 'file-posix' file child which was opened with the
17
'auto-read-only' property set.
18
19
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
20
Message-Id: <db118dbafe1955afbc0a18d3dd220931074ce349.1582893284.git.pkrempa@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
22
---
13
block/qcow2-bitmap.c | 10 ++++++++++
23
block/qcow2.c | 7 ++++++-
14
block/qcow2.c | 14 +++++++++++---
24
1 file changed, 6 insertions(+), 1 deletion(-)
15
2 files changed, 21 insertions(+), 3 deletions(-)
16
25
17
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-bitmap.c
20
+++ b/block/qcow2-bitmap.c
21
@@ -XXX,XX +XXX,XX @@ bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
22
bool found;
23
Qcow2BitmapList *bm_list;
24
25
+ if (s->qcow_version < 3) {
26
+ /* Without autoclear_features, we would always have to assume
27
+ * that a program without persistent dirty bitmap support has
28
+ * accessed this qcow2 file when opening it, and would thus
29
+ * have to drop all dirty bitmaps (defeating their purpose).
30
+ */
31
+ error_setg(errp, "Cannot store dirty bitmaps in qcow2 v2 files");
32
+ goto fail;
33
+ }
34
+
35
if (check_constraints_on_bitmap(bs, name, granularity, errp) != 0) {
36
goto fail;
37
}
38
diff --git a/block/qcow2.c b/block/qcow2.c
26
diff --git a/block/qcow2.c b/block/qcow2.c
39
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
40
--- a/block/qcow2.c
28
--- a/block/qcow2.c
41
+++ b/block/qcow2.c
29
+++ b/block/qcow2.c
42
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
30
@@ -XXX,XX +XXX,XX @@ fail:
43
}
31
static void qcow2_reopen_commit(BDRVReopenState *state)
44
32
{
45
if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) {
33
qcow2_update_options_commit(state->bs, state->opaque);
46
- warn_report("a program lacking bitmap support "
34
+ g_free(state->opaque);
47
- "modified this file, so all bitmaps are now "
35
+}
48
- "considered inconsistent");
36
+
49
+ if (s->qcow_version < 3) {
37
+static void qcow2_reopen_commit_post(BDRVReopenState *state)
50
+ /* Let's be a bit more specific */
38
+{
51
+ warn_report("This qcow2 v2 image contains bitmaps, but "
39
if (state->flags & BDRV_O_RDWR) {
52
+ "they may have been modified by a program "
40
Error *local_err = NULL;
53
+ "without persistent bitmap support; so now "
41
54
+ "they must all be considered inconsistent");
42
@@ -XXX,XX +XXX,XX @@ static void qcow2_reopen_commit(BDRVReopenState *state)
55
+ } else {
43
bdrv_get_node_name(state->bs));
56
+ warn_report("a program lacking bitmap support "
44
}
57
+ "modified this file, so all bitmaps are now "
45
}
58
+ "considered inconsistent");
46
- g_free(state->opaque);
59
+ }
47
}
60
error_printf("Some clusters may be leaked, "
48
61
"run 'qemu-img check -r' on the image "
49
static void qcow2_reopen_abort(BDRVReopenState *state)
62
"file to fix.");
50
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
51
.bdrv_close = qcow2_close,
52
.bdrv_reopen_prepare = qcow2_reopen_prepare,
53
.bdrv_reopen_commit = qcow2_reopen_commit,
54
+ .bdrv_reopen_commit_post = qcow2_reopen_commit_post,
55
.bdrv_reopen_abort = qcow2_reopen_abort,
56
.bdrv_join_options = qcow2_join_options,
57
.bdrv_child_perm = bdrv_format_default_perms,
63
--
58
--
64
2.13.6
59
2.20.1
65
60
66
61
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a new binary qemu-storage-daemon that doesn't yet do more than
2
some typical initialisation for tools and parsing the basic command
3
options --version, --help and --trace.
2
4
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
Even though this doesn't add any options yet that create things (like
4
Message-id: 20171129192411.6637-1-mreitz@redhat.com
6
--object or --blockdev), already document that we're planning to process
5
Reviewed-by: John Snow <jsnow@redhat.com>
7
them in the order they are given on the command line rather than trying
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
(and failing, like vl.c) to resolve dependencies between options
9
automatically.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Message-Id: <20200224143008.13362-2-kwolf@redhat.com>
13
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
15
---
8
tests/qemu-iotests/059 | 4 +++-
16
configure | 2 +-
9
1 file changed, 3 insertions(+), 1 deletion(-)
17
qemu-storage-daemon.c | 127 ++++++++++++++++++++++++++++++++++++++++++
18
Makefile | 1 +
19
3 files changed, 129 insertions(+), 1 deletion(-)
20
create mode 100644 qemu-storage-daemon.c
10
21
11
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
22
diff --git a/configure b/configure
12
index XXXXXXX..XXXXXXX 100755
23
index XXXXXXX..XXXXXXX 100755
13
--- a/tests/qemu-iotests/059
24
--- a/configure
14
+++ b/tests/qemu-iotests/059
25
+++ b/configure
15
@@ -XXX,XX +XXX,XX @@ done
26
@@ -XXX,XX +XXX,XX @@ tools=""
16
echo
27
if test "$want_tools" = "yes" ; then
17
echo "=== Testing afl image with a very large capacity ==="
28
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) qemu-edid\$(EXESUF) $tools"
18
_use_sample_img afl9.vmdk.bz2
29
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
19
-_img_info
30
- tools="qemu-nbd\$(EXESUF) $tools"
20
+# The sed makes this test pass on machines with little RAM
31
+ tools="qemu-nbd\$(EXESUF) qemu-storage-daemon\$(EXESUF) $tools"
21
+# (and also with 32 bit builds)
32
fi
22
+_img_info | sed -e 's/Cannot allocate memory/Invalid argument/'
33
if [ "$ivshmem" = "yes" ]; then
23
_cleanup_test_img
34
tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
24
35
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
25
# success, all done
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/qemu-storage-daemon.c
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * QEMU storage daemon
43
+ *
44
+ * Copyright (c) 2003-2008 Fabrice Bellard
45
+ * Copyright (c) 2019 Kevin Wolf <kwolf@redhat.com>
46
+ *
47
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
48
+ * of this software and associated documentation files (the "Software"), to deal
49
+ * in the Software without restriction, including without limitation the rights
50
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
51
+ * copies of the Software, and to permit persons to whom the Software is
52
+ * furnished to do so, subject to the following conditions:
53
+ *
54
+ * The above copyright notice and this permission notice shall be included in
55
+ * all copies or substantial portions of the Software.
56
+ *
57
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
60
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
61
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63
+ * THE SOFTWARE.
64
+ */
65
+
66
+#include "qemu/osdep.h"
67
+
68
+#include <getopt.h>
69
+
70
+#include "block/block.h"
71
+#include "crypto/init.h"
72
+
73
+#include "qapi/error.h"
74
+#include "qemu-common.h"
75
+#include "qemu-version.h"
76
+#include "qemu/config-file.h"
77
+#include "qemu/error-report.h"
78
+#include "qemu/log.h"
79
+#include "qemu/main-loop.h"
80
+#include "qemu/module.h"
81
+
82
+#include "trace/control.h"
83
+
84
+static void help(void)
85
+{
86
+ printf(
87
+"Usage: %s [options]\n"
88
+"QEMU storage daemon\n"
89
+"\n"
90
+" -h, --help display this help and exit\n"
91
+" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
92
+" specify tracing options\n"
93
+" -V, --version output version information and exit\n"
94
+"\n"
95
+QEMU_HELP_BOTTOM "\n",
96
+ error_get_progname());
97
+}
98
+
99
+static void process_options(int argc, char *argv[])
100
+{
101
+ int c;
102
+
103
+ static const struct option long_options[] = {
104
+ {"help", no_argument, NULL, 'h'},
105
+ {"trace", required_argument, NULL, 'T'},
106
+ {"version", no_argument, NULL, 'V'},
107
+ {0, 0, 0, 0}
108
+ };
109
+
110
+ /*
111
+ * In contrast to the system emulator, options are processed in the order
112
+ * they are given on the command lines. This means that things must be
113
+ * defined first before they can be referenced in another option.
114
+ */
115
+ while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
116
+ switch (c) {
117
+ case '?':
118
+ exit(EXIT_FAILURE);
119
+ case 'h':
120
+ help();
121
+ exit(EXIT_SUCCESS);
122
+ case 'T':
123
+ {
124
+ char *trace_file = trace_opt_parse(optarg);
125
+ trace_init_file(trace_file);
126
+ g_free(trace_file);
127
+ break;
128
+ }
129
+ case 'V':
130
+ printf("qemu-storage-daemon version "
131
+ QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
132
+ exit(EXIT_SUCCESS);
133
+ default:
134
+ g_assert_not_reached();
135
+ }
136
+ }
137
+ if (optind != argc) {
138
+ error_report("Unexpected argument: %s", argv[optind]);
139
+ exit(EXIT_FAILURE);
140
+ }
141
+}
142
+
143
+int main(int argc, char *argv[])
144
+{
145
+#ifdef CONFIG_POSIX
146
+ signal(SIGPIPE, SIG_IGN);
147
+#endif
148
+
149
+ error_init(argv[0]);
150
+ qemu_init_exec_dir(argv[0]);
151
+
152
+ module_call_init(MODULE_INIT_QOM);
153
+ module_call_init(MODULE_INIT_TRACE);
154
+ qemu_add_opts(&qemu_trace_opts);
155
+ qcrypto_init(&error_fatal);
156
+ bdrv_init();
157
+
158
+ if (!trace_init_backends()) {
159
+ return EXIT_FAILURE;
160
+ }
161
+ qemu_set_log(LOG_TRACE);
162
+
163
+ qemu_init_main_loop(&error_fatal);
164
+ process_options(argc, argv);
165
+
166
+ return EXIT_SUCCESS;
167
+}
168
diff --git a/Makefile b/Makefile
169
index XXXXXXX..XXXXXXX 100644
170
--- a/Makefile
171
+++ b/Makefile
172
@@ -XXX,XX +XXX,XX @@ qemu-img.o: qemu-img-cmds.h
173
qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
174
qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
175
qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
176
+qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
177
178
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
179
26
--
180
--
27
2.13.6
181
2.20.1
28
182
29
183
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
blockdev.c uses the arch_type constant, so before we can use the file in
2
tools (i.e. outside of the system emulator), we need to add a stub for
3
it. A new QEMU_ARCH_NONE is introduced for this case.
2
4
3
In order for 191 to work with an explicit refcount_bits or compat=0.10,
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
we should strip format-specific information from the output--and we can
6
Message-Id: <20200224143008.13362-3-kwolf@redhat.com>
5
do so by using _filter_img_info.
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/sysemu/arch_init.h | 2 ++
11
stubs/arch_type.c | 4 ++++
12
stubs/Makefile.objs | 1 +
13
3 files changed, 7 insertions(+)
14
create mode 100644 stubs/arch_type.c
6
15
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
8
Message-id: 20171123020832.8165-17-mreitz@redhat.com
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
tests/qemu-iotests/191 | 5 +-
13
tests/qemu-iotests/191.out | 313 +++++++++++++--------------------------------
14
2 files changed, 91 insertions(+), 227 deletions(-)
15
16
diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/191
19
+++ b/tests/qemu-iotests/191
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
21
. ./common.qemu
22
23
_supported_fmt qcow2
24
-_unsupported_imgopts compat=0.10
25
_supported_proto file
26
_supported_os Linux
27
28
@@ -XXX,XX +XXX,XX @@ echo === Check that both top and top2 point to base now ===
29
echo
30
31
_send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" |
32
- _filter_generated_node_ids | _filter_actual_image_size
33
+ _filter_generated_node_ids | _filter_actual_image_size | _filter_img_info
34
35
_send_qemu_cmd $h "{ 'execute': 'quit' }" "^}"
36
wait=1 _cleanup_qemu
37
@@ -XXX,XX +XXX,XX @@ echo === Check that both top and top2 point to base now ===
38
echo
39
40
_send_qemu_cmd $h "{ 'execute': 'query-named-block-nodes' }" "^}" |
41
- _filter_generated_node_ids | _filter_actual_image_size
42
+ _filter_generated_node_ids | _filter_actual_image_size | _filter_img_info
43
44
_send_qemu_cmd $h "{ 'execute': 'quit' }" "^}"
45
wait=1 _cleanup_qemu
46
diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out
47
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
48
--- a/tests/qemu-iotests/191.out
18
--- a/include/sysemu/arch_init.h
49
+++ b/tests/qemu-iotests/191.out
19
+++ b/include/sysemu/arch_init.h
50
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
20
@@ -XXX,XX +XXX,XX @@ enum {
51
"image": {
21
QEMU_ARCH_NIOS2 = (1 << 17),
52
"backing-image": {
22
QEMU_ARCH_HPPA = (1 << 18),
53
"virtual-size": 67108864,
23
QEMU_ARCH_RISCV = (1 << 19),
54
- "filename": "TEST_DIR/t.qcow2.base",
24
+
55
+ "filename": "TEST_DIR/t.IMGFMT.base",
25
+ QEMU_ARCH_NONE = (1 << 31),
56
"cluster-size": 65536,
26
};
57
- "format": "qcow2",
27
58
+ "format": "IMGFMT",
28
extern const uint32_t arch_type;
59
"actual-size": SIZE,
29
diff --git a/stubs/arch_type.c b/stubs/arch_type.c
60
- "format-specific": {
30
new file mode 100644
61
- "type": "qcow2",
31
index XXXXXXX..XXXXXXX
62
- "data": {
32
--- /dev/null
63
- "compat": "1.1",
33
+++ b/stubs/arch_type.c
64
- "lazy-refcounts": false,
34
@@ -XXX,XX +XXX,XX @@
65
- "refcount-bits": 16,
35
+#include "qemu/osdep.h"
66
- "corrupt": false
36
+#include "sysemu/arch_init.h"
67
- }
37
+
68
- },
38
+const uint32_t arch_type = QEMU_ARCH_NONE;
69
"dirty-flag": false
39
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
70
},
40
index XXXXXXX..XXXXXXX 100644
71
- "backing-filename-format": "qcow2",
41
--- a/stubs/Makefile.objs
72
+ "backing-filename-format": "IMGFMT",
42
+++ b/stubs/Makefile.objs
73
"virtual-size": 67108864,
43
@@ -XXX,XX +XXX,XX @@
74
- "filename": "TEST_DIR/t.qcow2.ovl2",
44
+stub-obj-y += arch_type.o
75
+ "filename": "TEST_DIR/t.IMGFMT.ovl2",
45
stub-obj-y += bdrv-next-monitor-owned.o
76
"cluster-size": 65536,
46
stub-obj-y += blk-commit-all.o
77
- "format": "qcow2",
47
stub-obj-y += blockdev-close-all-bdrv-states.o
78
+ "format": "IMGFMT",
79
"actual-size": SIZE,
80
- "format-specific": {
81
- "type": "qcow2",
82
- "data": {
83
- "compat": "1.1",
84
- "lazy-refcounts": false,
85
- "refcount-bits": 16,
86
- "corrupt": false
87
- }
88
- },
89
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
90
- "backing-filename": "TEST_DIR/t.qcow2.base",
91
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
92
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
93
"dirty-flag": false
94
},
95
"iops_wr": 0,
96
"ro": false,
97
"node-name": "top2",
98
"backing_file_depth": 1,
99
- "drv": "qcow2",
100
+ "drv": "IMGFMT",
101
"iops": 0,
102
"bps_wr": 0,
103
"write_threshold": 0,
104
- "backing_file": "TEST_DIR/t.qcow2.base",
105
+ "backing_file": "TEST_DIR/t.IMGFMT.base",
106
"encrypted": false,
107
"bps": 0,
108
"bps_rd": 0,
109
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
110
"direct": false,
111
"writeback": true
112
},
113
- "file": "TEST_DIR/t.qcow2.ovl2",
114
+ "file": "TEST_DIR/t.IMGFMT.ovl2",
115
"encryption_key_missing": false
116
},
117
{
118
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
119
"detect_zeroes": "off",
120
"image": {
121
"virtual-size": 197120,
122
- "filename": "TEST_DIR/t.qcow2.ovl2",
123
+ "filename": "TEST_DIR/t.IMGFMT.ovl2",
124
"format": "file",
125
"actual-size": SIZE,
126
"dirty-flag": false
127
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
128
"direct": false,
129
"writeback": true
130
},
131
- "file": "TEST_DIR/t.qcow2.ovl2",
132
+ "file": "TEST_DIR/t.IMGFMT.ovl2",
133
"encryption_key_missing": false
134
},
135
{
136
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
137
"image": {
138
"backing-image": {
139
"virtual-size": 67108864,
140
- "filename": "TEST_DIR/t.qcow2.base",
141
+ "filename": "TEST_DIR/t.IMGFMT.base",
142
"cluster-size": 65536,
143
- "format": "qcow2",
144
+ "format": "IMGFMT",
145
"actual-size": SIZE,
146
- "format-specific": {
147
- "type": "qcow2",
148
- "data": {
149
- "compat": "1.1",
150
- "lazy-refcounts": false,
151
- "refcount-bits": 16,
152
- "corrupt": false
153
- }
154
- },
155
"dirty-flag": false
156
},
157
- "backing-filename-format": "qcow2",
158
+ "backing-filename-format": "IMGFMT",
159
"virtual-size": 67108864,
160
- "filename": "TEST_DIR/t.qcow2",
161
+ "filename": "TEST_DIR/t.IMGFMT",
162
"cluster-size": 65536,
163
- "format": "qcow2",
164
+ "format": "IMGFMT",
165
"actual-size": SIZE,
166
- "format-specific": {
167
- "type": "qcow2",
168
- "data": {
169
- "compat": "1.1",
170
- "lazy-refcounts": false,
171
- "refcount-bits": 16,
172
- "corrupt": false
173
- }
174
- },
175
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
176
- "backing-filename": "TEST_DIR/t.qcow2.base",
177
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
178
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
179
"dirty-flag": false
180
},
181
"iops_wr": 0,
182
"ro": false,
183
"node-name": "top",
184
"backing_file_depth": 1,
185
- "drv": "qcow2",
186
+ "drv": "IMGFMT",
187
"iops": 0,
188
"bps_wr": 0,
189
"write_threshold": 0,
190
- "backing_file": "TEST_DIR/t.qcow2.base",
191
+ "backing_file": "TEST_DIR/t.IMGFMT.base",
192
"encrypted": false,
193
"bps": 0,
194
"bps_rd": 0,
195
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
196
"direct": false,
197
"writeback": true
198
},
199
- "file": "TEST_DIR/t.qcow2",
200
+ "file": "TEST_DIR/t.IMGFMT",
201
"encryption_key_missing": false
202
},
203
{
204
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
205
"detect_zeroes": "off",
206
"image": {
207
"virtual-size": 197120,
208
- "filename": "TEST_DIR/t.qcow2",
209
+ "filename": "TEST_DIR/t.IMGFMT",
210
"format": "file",
211
"actual-size": SIZE,
212
"dirty-flag": false
213
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
214
"direct": false,
215
"writeback": true
216
},
217
- "file": "TEST_DIR/t.qcow2",
218
+ "file": "TEST_DIR/t.IMGFMT",
219
"encryption_key_missing": false
220
},
221
{
222
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
223
"image": {
224
"backing-image": {
225
"virtual-size": 67108864,
226
- "filename": "TEST_DIR/t.qcow2.base",
227
+ "filename": "TEST_DIR/t.IMGFMT.base",
228
"cluster-size": 65536,
229
- "format": "qcow2",
230
+ "format": "IMGFMT",
231
"actual-size": SIZE,
232
- "format-specific": {
233
- "type": "qcow2",
234
- "data": {
235
- "compat": "1.1",
236
- "lazy-refcounts": false,
237
- "refcount-bits": 16,
238
- "corrupt": false
239
- }
240
- },
241
"dirty-flag": false
242
},
243
- "backing-filename-format": "qcow2",
244
+ "backing-filename-format": "IMGFMT",
245
"virtual-size": 67108864,
246
- "filename": "TEST_DIR/t.qcow2.mid",
247
+ "filename": "TEST_DIR/t.IMGFMT.mid",
248
"cluster-size": 65536,
249
- "format": "qcow2",
250
+ "format": "IMGFMT",
251
"actual-size": SIZE,
252
- "format-specific": {
253
- "type": "qcow2",
254
- "data": {
255
- "compat": "1.1",
256
- "lazy-refcounts": false,
257
- "refcount-bits": 16,
258
- "corrupt": false
259
- }
260
- },
261
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
262
- "backing-filename": "TEST_DIR/t.qcow2.base",
263
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
264
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
265
"dirty-flag": false
266
},
267
"iops_wr": 0,
268
"ro": false,
269
"node-name": "mid",
270
"backing_file_depth": 1,
271
- "drv": "qcow2",
272
+ "drv": "IMGFMT",
273
"iops": 0,
274
"bps_wr": 0,
275
"write_threshold": 0,
276
- "backing_file": "TEST_DIR/t.qcow2.base",
277
+ "backing_file": "TEST_DIR/t.IMGFMT.base",
278
"encrypted": false,
279
"bps": 0,
280
"bps_rd": 0,
281
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
282
"direct": false,
283
"writeback": true
284
},
285
- "file": "TEST_DIR/t.qcow2.mid",
286
+ "file": "TEST_DIR/t.IMGFMT.mid",
287
"encryption_key_missing": false
288
},
289
{
290
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
291
"detect_zeroes": "off",
292
"image": {
293
"virtual-size": 393216,
294
- "filename": "TEST_DIR/t.qcow2.mid",
295
+ "filename": "TEST_DIR/t.IMGFMT.mid",
296
"format": "file",
297
"actual-size": SIZE,
298
"dirty-flag": false
299
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
300
"direct": false,
301
"writeback": true
302
},
303
- "file": "TEST_DIR/t.qcow2.mid",
304
+ "file": "TEST_DIR/t.IMGFMT.mid",
305
"encryption_key_missing": false
306
},
307
{
308
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
309
"detect_zeroes": "off",
310
"image": {
311
"virtual-size": 67108864,
312
- "filename": "TEST_DIR/t.qcow2.base",
313
+ "filename": "TEST_DIR/t.IMGFMT.base",
314
"cluster-size": 65536,
315
- "format": "qcow2",
316
+ "format": "IMGFMT",
317
"actual-size": SIZE,
318
- "format-specific": {
319
- "type": "qcow2",
320
- "data": {
321
- "compat": "1.1",
322
- "lazy-refcounts": false,
323
- "refcount-bits": 16,
324
- "corrupt": false
325
- }
326
- },
327
"dirty-flag": false
328
},
329
"iops_wr": 0,
330
"ro": false,
331
"node-name": "base",
332
"backing_file_depth": 0,
333
- "drv": "qcow2",
334
+ "drv": "IMGFMT",
335
"iops": 0,
336
"bps_wr": 0,
337
"write_threshold": 0,
338
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
339
"direct": false,
340
"writeback": true
341
},
342
- "file": "TEST_DIR/t.qcow2.base",
343
+ "file": "TEST_DIR/t.IMGFMT.base",
344
"encryption_key_missing": false
345
},
346
{
347
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
348
"detect_zeroes": "off",
349
"image": {
350
"virtual-size": 393216,
351
- "filename": "TEST_DIR/t.qcow2.base",
352
+ "filename": "TEST_DIR/t.IMGFMT.base",
353
"format": "file",
354
"actual-size": SIZE,
355
"dirty-flag": false
356
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
357
"direct": false,
358
"writeback": true
359
},
360
- "file": "TEST_DIR/t.qcow2.base",
361
+ "file": "TEST_DIR/t.IMGFMT.base",
362
"encryption_key_missing": false
363
}
364
]
365
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
366
"image": {
367
"backing-image": {
368
"virtual-size": 67108864,
369
- "filename": "TEST_DIR/t.qcow2.base",
370
+ "filename": "TEST_DIR/t.IMGFMT.base",
371
"cluster-size": 65536,
372
- "format": "qcow2",
373
+ "format": "IMGFMT",
374
"actual-size": SIZE,
375
- "format-specific": {
376
- "type": "qcow2",
377
- "data": {
378
- "compat": "1.1",
379
- "lazy-refcounts": false,
380
- "refcount-bits": 16,
381
- "corrupt": false
382
- }
383
- },
384
"dirty-flag": false
385
},
386
- "backing-filename-format": "qcow2",
387
+ "backing-filename-format": "IMGFMT",
388
"virtual-size": 67108864,
389
- "filename": "TEST_DIR/t.qcow2.ovl2",
390
+ "filename": "TEST_DIR/t.IMGFMT.ovl2",
391
"cluster-size": 65536,
392
- "format": "qcow2",
393
+ "format": "IMGFMT",
394
"actual-size": SIZE,
395
- "format-specific": {
396
- "type": "qcow2",
397
- "data": {
398
- "compat": "1.1",
399
- "lazy-refcounts": false,
400
- "refcount-bits": 16,
401
- "corrupt": false
402
- }
403
- },
404
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
405
- "backing-filename": "TEST_DIR/t.qcow2.base",
406
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
407
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
408
"dirty-flag": false
409
},
410
"iops_wr": 0,
411
"ro": true,
412
"node-name": "NODE_NAME",
413
"backing_file_depth": 1,
414
- "drv": "qcow2",
415
+ "drv": "IMGFMT",
416
"iops": 0,
417
"bps_wr": 0,
418
"write_threshold": 0,
419
- "backing_file": "TEST_DIR/t.qcow2.base",
420
+ "backing_file": "TEST_DIR/t.IMGFMT.base",
421
"encrypted": false,
422
"bps": 0,
423
"bps_rd": 0,
424
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
425
"direct": false,
426
"writeback": true
427
},
428
- "file": "TEST_DIR/t.qcow2.ovl2",
429
+ "file": "TEST_DIR/t.IMGFMT.ovl2",
430
"encryption_key_missing": false
431
},
432
{
433
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
434
"detect_zeroes": "off",
435
"image": {
436
"virtual-size": 197120,
437
- "filename": "TEST_DIR/t.qcow2.ovl2",
438
+ "filename": "TEST_DIR/t.IMGFMT.ovl2",
439
"format": "file",
440
"actual-size": SIZE,
441
"dirty-flag": false
442
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
443
"direct": false,
444
"writeback": true
445
},
446
- "file": "TEST_DIR/t.qcow2.ovl2",
447
+ "file": "TEST_DIR/t.IMGFMT.ovl2",
448
"encryption_key_missing": false
449
},
450
{
451
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
452
"backing-image": {
453
"backing-image": {
454
"virtual-size": 67108864,
455
- "filename": "TEST_DIR/t.qcow2.base",
456
+ "filename": "TEST_DIR/t.IMGFMT.base",
457
"cluster-size": 65536,
458
- "format": "qcow2",
459
+ "format": "IMGFMT",
460
"actual-size": SIZE,
461
- "format-specific": {
462
- "type": "qcow2",
463
- "data": {
464
- "compat": "1.1",
465
- "lazy-refcounts": false,
466
- "refcount-bits": 16,
467
- "corrupt": false
468
- }
469
- },
470
"dirty-flag": false
471
},
472
- "backing-filename-format": "qcow2",
473
+ "backing-filename-format": "IMGFMT",
474
"virtual-size": 67108864,
475
- "filename": "TEST_DIR/t.qcow2.ovl2",
476
+ "filename": "TEST_DIR/t.IMGFMT.ovl2",
477
"cluster-size": 65536,
478
- "format": "qcow2",
479
+ "format": "IMGFMT",
480
"actual-size": SIZE,
481
- "format-specific": {
482
- "type": "qcow2",
483
- "data": {
484
- "compat": "1.1",
485
- "lazy-refcounts": false,
486
- "refcount-bits": 16,
487
- "corrupt": false
488
- }
489
- },
490
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
491
- "backing-filename": "TEST_DIR/t.qcow2.base",
492
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
493
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
494
"dirty-flag": false
495
},
496
- "backing-filename-format": "qcow2",
497
+ "backing-filename-format": "IMGFMT",
498
"virtual-size": 67108864,
499
- "filename": "TEST_DIR/t.qcow2.ovl3",
500
+ "filename": "TEST_DIR/t.IMGFMT.ovl3",
501
"cluster-size": 65536,
502
- "format": "qcow2",
503
+ "format": "IMGFMT",
504
"actual-size": SIZE,
505
- "format-specific": {
506
- "type": "qcow2",
507
- "data": {
508
- "compat": "1.1",
509
- "lazy-refcounts": false,
510
- "refcount-bits": 16,
511
- "corrupt": false
512
- }
513
- },
514
- "full-backing-filename": "TEST_DIR/t.qcow2.ovl2",
515
- "backing-filename": "TEST_DIR/t.qcow2.ovl2",
516
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.ovl2",
517
+ "backing-filename": "TEST_DIR/t.IMGFMT.ovl2",
518
"dirty-flag": false
519
},
520
"iops_wr": 0,
521
"ro": false,
522
"node-name": "top2",
523
"backing_file_depth": 2,
524
- "drv": "qcow2",
525
+ "drv": "IMGFMT",
526
"iops": 0,
527
"bps_wr": 0,
528
"write_threshold": 0,
529
- "backing_file": "TEST_DIR/t.qcow2.ovl2",
530
+ "backing_file": "TEST_DIR/t.IMGFMT.ovl2",
531
"encrypted": false,
532
"bps": 0,
533
"bps_rd": 0,
534
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
535
"direct": false,
536
"writeback": true
537
},
538
- "file": "TEST_DIR/t.qcow2.ovl3",
539
+ "file": "TEST_DIR/t.IMGFMT.ovl3",
540
"encryption_key_missing": false
541
},
542
{
543
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
544
"detect_zeroes": "off",
545
"image": {
546
"virtual-size": 197120,
547
- "filename": "TEST_DIR/t.qcow2.ovl3",
548
+ "filename": "TEST_DIR/t.IMGFMT.ovl3",
549
"format": "file",
550
"actual-size": SIZE,
551
"dirty-flag": false
552
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
553
"direct": false,
554
"writeback": true
555
},
556
- "file": "TEST_DIR/t.qcow2.ovl3",
557
+ "file": "TEST_DIR/t.IMGFMT.ovl3",
558
"encryption_key_missing": false
559
},
560
{
561
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
562
"detect_zeroes": "off",
563
"image": {
564
"virtual-size": 67108864,
565
- "filename": "TEST_DIR/t.qcow2.base",
566
+ "filename": "TEST_DIR/t.IMGFMT.base",
567
"cluster-size": 65536,
568
- "format": "qcow2",
569
+ "format": "IMGFMT",
570
"actual-size": SIZE,
571
- "format-specific": {
572
- "type": "qcow2",
573
- "data": {
574
- "compat": "1.1",
575
- "lazy-refcounts": false,
576
- "refcount-bits": 16,
577
- "corrupt": false
578
- }
579
- },
580
"dirty-flag": false
581
},
582
"iops_wr": 0,
583
"ro": true,
584
"node-name": "NODE_NAME",
585
"backing_file_depth": 0,
586
- "drv": "qcow2",
587
+ "drv": "IMGFMT",
588
"iops": 0,
589
"bps_wr": 0,
590
"write_threshold": 0,
591
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
592
"direct": false,
593
"writeback": true
594
},
595
- "file": "TEST_DIR/t.qcow2.base",
596
+ "file": "TEST_DIR/t.IMGFMT.base",
597
"encryption_key_missing": false
598
},
599
{
600
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
601
"detect_zeroes": "off",
602
"image": {
603
"virtual-size": 393216,
604
- "filename": "TEST_DIR/t.qcow2.base",
605
+ "filename": "TEST_DIR/t.IMGFMT.base",
606
"format": "file",
607
"actual-size": SIZE,
608
"dirty-flag": false
609
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
610
"direct": false,
611
"writeback": true
612
},
613
- "file": "TEST_DIR/t.qcow2.base",
614
+ "file": "TEST_DIR/t.IMGFMT.base",
615
"encryption_key_missing": false
616
},
617
{
618
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
619
"image": {
620
"backing-image": {
621
"virtual-size": 67108864,
622
- "filename": "TEST_DIR/t.qcow2.base",
623
+ "filename": "TEST_DIR/t.IMGFMT.base",
624
"cluster-size": 65536,
625
- "format": "qcow2",
626
+ "format": "IMGFMT",
627
"actual-size": SIZE,
628
- "format-specific": {
629
- "type": "qcow2",
630
- "data": {
631
- "compat": "1.1",
632
- "lazy-refcounts": false,
633
- "refcount-bits": 16,
634
- "corrupt": false
635
- }
636
- },
637
"dirty-flag": false
638
},
639
- "backing-filename-format": "qcow2",
640
+ "backing-filename-format": "IMGFMT",
641
"virtual-size": 67108864,
642
- "filename": "TEST_DIR/t.qcow2",
643
+ "filename": "TEST_DIR/t.IMGFMT",
644
"cluster-size": 65536,
645
- "format": "qcow2",
646
+ "format": "IMGFMT",
647
"actual-size": SIZE,
648
- "format-specific": {
649
- "type": "qcow2",
650
- "data": {
651
- "compat": "1.1",
652
- "lazy-refcounts": false,
653
- "refcount-bits": 16,
654
- "corrupt": false
655
- }
656
- },
657
- "full-backing-filename": "TEST_DIR/t.qcow2.base",
658
- "backing-filename": "TEST_DIR/t.qcow2.base",
659
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
660
+ "backing-filename": "TEST_DIR/t.IMGFMT.base",
661
"dirty-flag": false
662
},
663
"iops_wr": 0,
664
"ro": false,
665
"node-name": "top",
666
"backing_file_depth": 1,
667
- "drv": "qcow2",
668
+ "drv": "IMGFMT",
669
"iops": 0,
670
"bps_wr": 0,
671
"write_threshold": 0,
672
- "backing_file": "TEST_DIR/t.qcow2.base",
673
+ "backing_file": "TEST_DIR/t.IMGFMT.base",
674
"encrypted": false,
675
"bps": 0,
676
"bps_rd": 0,
677
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
678
"direct": false,
679
"writeback": true
680
},
681
- "file": "TEST_DIR/t.qcow2",
682
+ "file": "TEST_DIR/t.IMGFMT",
683
"encryption_key_missing": false
684
},
685
{
686
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
687
"detect_zeroes": "off",
688
"image": {
689
"virtual-size": 197120,
690
- "filename": "TEST_DIR/t.qcow2",
691
+ "filename": "TEST_DIR/t.IMGFMT",
692
"format": "file",
693
"actual-size": SIZE,
694
"dirty-flag": false
695
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 1048576
696
"direct": false,
697
"writeback": true
698
},
699
- "file": "TEST_DIR/t.qcow2",
700
+ "file": "TEST_DIR/t.IMGFMT",
701
"encryption_key_missing": false
702
}
703
]
704
--
48
--
705
2.13.6
49
2.20.1
706
50
707
51
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
These commands make only sense for system emulators and their
2
implementations call functions that don't exist in tools (e.g. to
3
resolve qdev IDs). Move them out so that blockdev.c can be linked to
4
qemu-storage-daemon.
2
5
3
051 has both compat=1.1 and compat=0.10 tests (once it uses
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
lazy_refcounts, once it tests that setting them does not work).
7
Message-Id: <20200224143008.13362-4-kwolf@redhat.com>
5
For the compat=0.10 tests, it already explicitly creates a suitable
8
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
6
image. So let's just ignore the user-specified compat level for the
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
lazy_refcounts test and explicitly create a compat=1.1 image there, too.
10
---
11
block/qapi-sysemu.c | 590 ++++++++++++++++++++++++++++++++++++++++++++
12
blockdev.c | 559 -----------------------------------------
13
block/Makefile.objs | 2 +
14
3 files changed, 592 insertions(+), 559 deletions(-)
15
create mode 100644 block/qapi-sysemu.c
8
16
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
10
Message-id: 20171123020832.8165-12-mreitz@redhat.com
18
new file mode 100644
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
index XXXXXXX..XXXXXXX
12
---
20
--- /dev/null
13
tests/qemu-iotests/051 | 2 ++
21
+++ b/block/qapi-sysemu.c
14
tests/qemu-iotests/051.out | 1 +
22
@@ -XXX,XX +XXX,XX @@
15
tests/qemu-iotests/051.pc.out | 1 +
23
+/*
16
3 files changed, 4 insertions(+)
24
+ * QMP command handlers specific to the system emulators
17
25
+ *
18
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
26
+ * Copyright (c) 2003-2008 Fabrice Bellard
19
index XXXXXXX..XXXXXXX 100755
27
+ *
20
--- a/tests/qemu-iotests/051
28
+ * This work is licensed under the terms of the GNU GPL, version 2 or
21
+++ b/tests/qemu-iotests/051
29
+ * later. See the COPYING file in the top-level directory.
22
@@ -XXX,XX +XXX,XX @@ echo
30
+ *
23
echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
31
+ * This file incorporates work covered by the following copyright and
24
echo
32
+ * permission notice:
25
33
+ *
26
+_make_test_img -o compat=1.1 "$size"
34
+ * Copyright (c) 2003-2008 Fabrice Bellard
27
+
35
+ *
28
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on
36
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
29
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off
37
+ * of this software and associated documentation files (the "Software"), to deal
30
run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=
38
+ * in the Software without restriction, including without limitation the rights
31
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
39
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
+ * copies of the Software, and to permit persons to whom the Software is
41
+ * furnished to do so, subject to the following conditions:
42
+ *
43
+ * The above copyright notice and this permission notice shall be included in
44
+ * all copies or substantial portions of the Software.
45
+ *
46
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
49
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52
+ * THE SOFTWARE.
53
+ */
54
+
55
+#include "qemu/osdep.h"
56
+
57
+#include "qapi/error.h"
58
+#include "qapi/qapi-commands-block.h"
59
+#include "qapi/qmp/qdict.h"
60
+#include "sysemu/block-backend.h"
61
+#include "sysemu/blockdev.h"
62
+
63
+static BlockBackend *qmp_get_blk(const char *blk_name, const char *qdev_id,
64
+ Error **errp)
65
+{
66
+ BlockBackend *blk;
67
+
68
+ if (!blk_name == !qdev_id) {
69
+ error_setg(errp, "Need exactly one of 'device' and 'id'");
70
+ return NULL;
71
+ }
72
+
73
+ if (qdev_id) {
74
+ blk = blk_by_qdev_id(qdev_id, errp);
75
+ } else {
76
+ blk = blk_by_name(blk_name);
77
+ if (blk == NULL) {
78
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
79
+ "Device '%s' not found", blk_name);
80
+ }
81
+ }
82
+
83
+ return blk;
84
+}
85
+
86
+/*
87
+ * Attempt to open the tray of @device.
88
+ * If @force, ignore its tray lock.
89
+ * Else, if the tray is locked, don't open it, but ask the guest to open it.
90
+ * On error, store an error through @errp and return -errno.
91
+ * If @device does not exist, return -ENODEV.
92
+ * If it has no removable media, return -ENOTSUP.
93
+ * If it has no tray, return -ENOSYS.
94
+ * If the guest was asked to open the tray, return -EINPROGRESS.
95
+ * Else, return 0.
96
+ */
97
+static int do_open_tray(const char *blk_name, const char *qdev_id,
98
+ bool force, Error **errp)
99
+{
100
+ BlockBackend *blk;
101
+ const char *device = qdev_id ?: blk_name;
102
+ bool locked;
103
+
104
+ blk = qmp_get_blk(blk_name, qdev_id, errp);
105
+ if (!blk) {
106
+ return -ENODEV;
107
+ }
108
+
109
+ if (!blk_dev_has_removable_media(blk)) {
110
+ error_setg(errp, "Device '%s' is not removable", device);
111
+ return -ENOTSUP;
112
+ }
113
+
114
+ if (!blk_dev_has_tray(blk)) {
115
+ error_setg(errp, "Device '%s' does not have a tray", device);
116
+ return -ENOSYS;
117
+ }
118
+
119
+ if (blk_dev_is_tray_open(blk)) {
120
+ return 0;
121
+ }
122
+
123
+ locked = blk_dev_is_medium_locked(blk);
124
+ if (locked) {
125
+ blk_dev_eject_request(blk, force);
126
+ }
127
+
128
+ if (!locked || force) {
129
+ blk_dev_change_media_cb(blk, false, &error_abort);
130
+ }
131
+
132
+ if (locked && !force) {
133
+ error_setg(errp, "Device '%s' is locked and force was not specified, "
134
+ "wait for tray to open and try again", device);
135
+ return -EINPROGRESS;
136
+ }
137
+
138
+ return 0;
139
+}
140
+
141
+void qmp_blockdev_open_tray(bool has_device, const char *device,
142
+ bool has_id, const char *id,
143
+ bool has_force, bool force,
144
+ Error **errp)
145
+{
146
+ Error *local_err = NULL;
147
+ int rc;
148
+
149
+ if (!has_force) {
150
+ force = false;
151
+ }
152
+ rc = do_open_tray(has_device ? device : NULL,
153
+ has_id ? id : NULL,
154
+ force, &local_err);
155
+ if (rc && rc != -ENOSYS && rc != -EINPROGRESS) {
156
+ error_propagate(errp, local_err);
157
+ return;
158
+ }
159
+ error_free(local_err);
160
+}
161
+
162
+void qmp_blockdev_close_tray(bool has_device, const char *device,
163
+ bool has_id, const char *id,
164
+ Error **errp)
165
+{
166
+ BlockBackend *blk;
167
+ Error *local_err = NULL;
168
+
169
+ device = has_device ? device : NULL;
170
+ id = has_id ? id : NULL;
171
+
172
+ blk = qmp_get_blk(device, id, errp);
173
+ if (!blk) {
174
+ return;
175
+ }
176
+
177
+ if (!blk_dev_has_removable_media(blk)) {
178
+ error_setg(errp, "Device '%s' is not removable", device ?: id);
179
+ return;
180
+ }
181
+
182
+ if (!blk_dev_has_tray(blk)) {
183
+ /* Ignore this command on tray-less devices */
184
+ return;
185
+ }
186
+
187
+ if (!blk_dev_is_tray_open(blk)) {
188
+ return;
189
+ }
190
+
191
+ blk_dev_change_media_cb(blk, true, &local_err);
192
+ if (local_err) {
193
+ error_propagate(errp, local_err);
194
+ return;
195
+ }
196
+}
197
+
198
+static void blockdev_remove_medium(bool has_device, const char *device,
199
+ bool has_id, const char *id, Error **errp)
200
+{
201
+ BlockBackend *blk;
202
+ BlockDriverState *bs;
203
+ AioContext *aio_context;
204
+ bool has_attached_device;
205
+
206
+ device = has_device ? device : NULL;
207
+ id = has_id ? id : NULL;
208
+
209
+ blk = qmp_get_blk(device, id, errp);
210
+ if (!blk) {
211
+ return;
212
+ }
213
+
214
+ /* For BBs without a device, we can exchange the BDS tree at will */
215
+ has_attached_device = blk_get_attached_dev(blk);
216
+
217
+ if (has_attached_device && !blk_dev_has_removable_media(blk)) {
218
+ error_setg(errp, "Device '%s' is not removable", device ?: id);
219
+ return;
220
+ }
221
+
222
+ if (has_attached_device && blk_dev_has_tray(blk) &&
223
+ !blk_dev_is_tray_open(blk))
224
+ {
225
+ error_setg(errp, "Tray of device '%s' is not open", device ?: id);
226
+ return;
227
+ }
228
+
229
+ bs = blk_bs(blk);
230
+ if (!bs) {
231
+ return;
232
+ }
233
+
234
+ aio_context = bdrv_get_aio_context(bs);
235
+ aio_context_acquire(aio_context);
236
+
237
+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
238
+ goto out;
239
+ }
240
+
241
+ blk_remove_bs(blk);
242
+
243
+ if (!blk_dev_has_tray(blk)) {
244
+ /* For tray-less devices, blockdev-open-tray is a no-op (or may not be
245
+ * called at all); therefore, the medium needs to be ejected here.
246
+ * Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load
247
+ * value passed here (i.e. false). */
248
+ blk_dev_change_media_cb(blk, false, &error_abort);
249
+ }
250
+
251
+out:
252
+ aio_context_release(aio_context);
253
+}
254
+
255
+void qmp_blockdev_remove_medium(const char *id, Error **errp)
256
+{
257
+ blockdev_remove_medium(false, NULL, true, id, errp);
258
+}
259
+
260
+static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
261
+ BlockDriverState *bs, Error **errp)
262
+{
263
+ Error *local_err = NULL;
264
+ bool has_device;
265
+ int ret;
266
+
267
+ /* For BBs without a device, we can exchange the BDS tree at will */
268
+ has_device = blk_get_attached_dev(blk);
269
+
270
+ if (has_device && !blk_dev_has_removable_media(blk)) {
271
+ error_setg(errp, "Device is not removable");
272
+ return;
273
+ }
274
+
275
+ if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) {
276
+ error_setg(errp, "Tray of the device is not open");
277
+ return;
278
+ }
279
+
280
+ if (blk_bs(blk)) {
281
+ error_setg(errp, "There already is a medium in the device");
282
+ return;
283
+ }
284
+
285
+ ret = blk_insert_bs(blk, bs, errp);
286
+ if (ret < 0) {
287
+ return;
288
+ }
289
+
290
+ if (!blk_dev_has_tray(blk)) {
291
+ /* For tray-less devices, blockdev-close-tray is a no-op (or may not be
292
+ * called at all); therefore, the medium needs to be pushed into the
293
+ * slot here.
294
+ * Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load
295
+ * value passed here (i.e. true). */
296
+ blk_dev_change_media_cb(blk, true, &local_err);
297
+ if (local_err) {
298
+ error_propagate(errp, local_err);
299
+ blk_remove_bs(blk);
300
+ return;
301
+ }
302
+ }
303
+}
304
+
305
+static void blockdev_insert_medium(bool has_device, const char *device,
306
+ bool has_id, const char *id,
307
+ const char *node_name, Error **errp)
308
+{
309
+ BlockBackend *blk;
310
+ BlockDriverState *bs;
311
+
312
+ blk = qmp_get_blk(has_device ? device : NULL,
313
+ has_id ? id : NULL,
314
+ errp);
315
+ if (!blk) {
316
+ return;
317
+ }
318
+
319
+ bs = bdrv_find_node(node_name);
320
+ if (!bs) {
321
+ error_setg(errp, "Node '%s' not found", node_name);
322
+ return;
323
+ }
324
+
325
+ if (bdrv_has_blk(bs)) {
326
+ error_setg(errp, "Node '%s' is already in use", node_name);
327
+ return;
328
+ }
329
+
330
+ qmp_blockdev_insert_anon_medium(blk, bs, errp);
331
+}
332
+
333
+void qmp_blockdev_insert_medium(const char *id, const char *node_name,
334
+ Error **errp)
335
+{
336
+ blockdev_insert_medium(false, NULL, true, id, node_name, errp);
337
+}
338
+
339
+void qmp_blockdev_change_medium(bool has_device, const char *device,
340
+ bool has_id, const char *id,
341
+ const char *filename,
342
+ bool has_format, const char *format,
343
+ bool has_read_only,
344
+ BlockdevChangeReadOnlyMode read_only,
345
+ Error **errp)
346
+{
347
+ BlockBackend *blk;
348
+ BlockDriverState *medium_bs = NULL;
349
+ int bdrv_flags;
350
+ bool detect_zeroes;
351
+ int rc;
352
+ QDict *options = NULL;
353
+ Error *err = NULL;
354
+
355
+ blk = qmp_get_blk(has_device ? device : NULL,
356
+ has_id ? id : NULL,
357
+ errp);
358
+ if (!blk) {
359
+ goto fail;
360
+ }
361
+
362
+ if (blk_bs(blk)) {
363
+ blk_update_root_state(blk);
364
+ }
365
+
366
+ bdrv_flags = blk_get_open_flags_from_root_state(blk);
367
+ bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
368
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
369
+
370
+ if (!has_read_only) {
371
+ read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
372
+ }
373
+
374
+ switch (read_only) {
375
+ case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN:
376
+ break;
377
+
378
+ case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY:
379
+ bdrv_flags &= ~BDRV_O_RDWR;
380
+ break;
381
+
382
+ case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE:
383
+ bdrv_flags |= BDRV_O_RDWR;
384
+ break;
385
+
386
+ default:
387
+ abort();
388
+ }
389
+
390
+ options = qdict_new();
391
+ detect_zeroes = blk_get_detect_zeroes_from_root_state(blk);
392
+ qdict_put_str(options, "detect-zeroes", detect_zeroes ? "on" : "off");
393
+
394
+ if (has_format) {
395
+ qdict_put_str(options, "driver", format);
396
+ }
397
+
398
+ medium_bs = bdrv_open(filename, NULL, options, bdrv_flags, errp);
399
+ if (!medium_bs) {
400
+ goto fail;
401
+ }
402
+
403
+ rc = do_open_tray(has_device ? device : NULL,
404
+ has_id ? id : NULL,
405
+ false, &err);
406
+ if (rc && rc != -ENOSYS) {
407
+ error_propagate(errp, err);
408
+ goto fail;
409
+ }
410
+ error_free(err);
411
+ err = NULL;
412
+
413
+ blockdev_remove_medium(has_device, device, has_id, id, &err);
414
+ if (err) {
415
+ error_propagate(errp, err);
416
+ goto fail;
417
+ }
418
+
419
+ qmp_blockdev_insert_anon_medium(blk, medium_bs, &err);
420
+ if (err) {
421
+ error_propagate(errp, err);
422
+ goto fail;
423
+ }
424
+
425
+ qmp_blockdev_close_tray(has_device, device, has_id, id, errp);
426
+
427
+fail:
428
+ /* If the medium has been inserted, the device has its own reference, so
429
+ * ours must be relinquished; and if it has not been inserted successfully,
430
+ * the reference must be relinquished anyway */
431
+ bdrv_unref(medium_bs);
432
+}
433
+
434
+void qmp_eject(bool has_device, const char *device,
435
+ bool has_id, const char *id,
436
+ bool has_force, bool force, Error **errp)
437
+{
438
+ Error *local_err = NULL;
439
+ int rc;
440
+
441
+ if (!has_force) {
442
+ force = false;
443
+ }
444
+
445
+ rc = do_open_tray(has_device ? device : NULL,
446
+ has_id ? id : NULL,
447
+ force, &local_err);
448
+ if (rc && rc != -ENOSYS) {
449
+ error_propagate(errp, local_err);
450
+ return;
451
+ }
452
+ error_free(local_err);
453
+
454
+ blockdev_remove_medium(has_device, device, has_id, id, errp);
455
+}
456
+
457
+/* throttling disk I/O limits */
458
+void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
459
+{
460
+ ThrottleConfig cfg;
461
+ BlockDriverState *bs;
462
+ BlockBackend *blk;
463
+ AioContext *aio_context;
464
+
465
+ blk = qmp_get_blk(arg->has_device ? arg->device : NULL,
466
+ arg->has_id ? arg->id : NULL,
467
+ errp);
468
+ if (!blk) {
469
+ return;
470
+ }
471
+
472
+ aio_context = blk_get_aio_context(blk);
473
+ aio_context_acquire(aio_context);
474
+
475
+ bs = blk_bs(blk);
476
+ if (!bs) {
477
+ error_setg(errp, "Device has no medium");
478
+ goto out;
479
+ }
480
+
481
+ throttle_config_init(&cfg);
482
+ cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps;
483
+ cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd;
484
+ cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr;
485
+
486
+ cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops;
487
+ cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd;
488
+ cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr;
489
+
490
+ if (arg->has_bps_max) {
491
+ cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max;
492
+ }
493
+ if (arg->has_bps_rd_max) {
494
+ cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max;
495
+ }
496
+ if (arg->has_bps_wr_max) {
497
+ cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max;
498
+ }
499
+ if (arg->has_iops_max) {
500
+ cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max;
501
+ }
502
+ if (arg->has_iops_rd_max) {
503
+ cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max;
504
+ }
505
+ if (arg->has_iops_wr_max) {
506
+ cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max;
507
+ }
508
+
509
+ if (arg->has_bps_max_length) {
510
+ cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length;
511
+ }
512
+ if (arg->has_bps_rd_max_length) {
513
+ cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length;
514
+ }
515
+ if (arg->has_bps_wr_max_length) {
516
+ cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length;
517
+ }
518
+ if (arg->has_iops_max_length) {
519
+ cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length;
520
+ }
521
+ if (arg->has_iops_rd_max_length) {
522
+ cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length;
523
+ }
524
+ if (arg->has_iops_wr_max_length) {
525
+ cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length;
526
+ }
527
+
528
+ if (arg->has_iops_size) {
529
+ cfg.op_size = arg->iops_size;
530
+ }
531
+
532
+ if (!throttle_is_valid(&cfg, errp)) {
533
+ goto out;
534
+ }
535
+
536
+ if (throttle_enabled(&cfg)) {
537
+ /* Enable I/O limits if they're not enabled yet, otherwise
538
+ * just update the throttling group. */
539
+ if (!blk_get_public(blk)->throttle_group_member.throttle_state) {
540
+ blk_io_limits_enable(blk,
541
+ arg->has_group ? arg->group :
542
+ arg->has_device ? arg->device :
543
+ arg->id);
544
+ } else if (arg->has_group) {
545
+ blk_io_limits_update_group(blk, arg->group);
546
+ }
547
+ /* Set the new throttling configuration */
548
+ blk_set_io_limits(blk, &cfg);
549
+ } else if (blk_get_public(blk)->throttle_group_member.throttle_state) {
550
+ /* If all throttling settings are set to 0, disable I/O limits */
551
+ blk_io_limits_disable(blk);
552
+ }
553
+
554
+out:
555
+ aio_context_release(aio_context);
556
+}
557
+
558
+void qmp_block_latency_histogram_set(
559
+ const char *id,
560
+ bool has_boundaries, uint64List *boundaries,
561
+ bool has_boundaries_read, uint64List *boundaries_read,
562
+ bool has_boundaries_write, uint64List *boundaries_write,
563
+ bool has_boundaries_flush, uint64List *boundaries_flush,
564
+ Error **errp)
565
+{
566
+ BlockBackend *blk = qmp_get_blk(NULL, id, errp);
567
+ BlockAcctStats *stats;
568
+ int ret;
569
+
570
+ if (!blk) {
571
+ return;
572
+ }
573
+
574
+ stats = blk_get_stats(blk);
575
+
576
+ if (!has_boundaries && !has_boundaries_read && !has_boundaries_write &&
577
+ !has_boundaries_flush)
578
+ {
579
+ block_latency_histograms_clear(stats);
580
+ return;
581
+ }
582
+
583
+ if (has_boundaries || has_boundaries_read) {
584
+ ret = block_latency_histogram_set(
585
+ stats, BLOCK_ACCT_READ,
586
+ has_boundaries_read ? boundaries_read : boundaries);
587
+ if (ret) {
588
+ error_setg(errp, "Device '%s' set read boundaries fail", id);
589
+ return;
590
+ }
591
+ }
592
+
593
+ if (has_boundaries || has_boundaries_write) {
594
+ ret = block_latency_histogram_set(
595
+ stats, BLOCK_ACCT_WRITE,
596
+ has_boundaries_write ? boundaries_write : boundaries);
597
+ if (ret) {
598
+ error_setg(errp, "Device '%s' set write boundaries fail", id);
599
+ return;
600
+ }
601
+ }
602
+
603
+ if (has_boundaries || has_boundaries_flush) {
604
+ ret = block_latency_histogram_set(
605
+ stats, BLOCK_ACCT_FLUSH,
606
+ has_boundaries_flush ? boundaries_flush : boundaries);
607
+ if (ret) {
608
+ error_setg(errp, "Device '%s' set flush boundaries fail", id);
609
+ return;
610
+ }
611
+ }
612
+}
613
diff --git a/blockdev.c b/blockdev.c
32
index XXXXXXX..XXXXXXX 100644
614
index XXXXXXX..XXXXXXX 100644
33
--- a/tests/qemu-iotests/051.out
615
--- a/blockdev.c
34
+++ b/tests/qemu-iotests/051.out
616
+++ b/blockdev.c
35
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
617
@@ -XXX,XX +XXX,XX @@
36
618
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
37
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
619
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
38
620
39
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
621
-static int do_open_tray(const char *blk_name, const char *qdev_id,
40
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
622
- bool force, Error **errp);
41
QEMU X.Y.Z monitor - type 'help' for more information
623
-static void blockdev_remove_medium(bool has_device, const char *device,
42
(qemu) quit
624
- bool has_id, const char *id, Error **errp);
43
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
625
-static void blockdev_insert_medium(bool has_device, const char *device,
626
- bool has_id, const char *id,
627
- const char *node_name, Error **errp);
628
-
629
static const char *const if_name[IF_COUNT] = {
630
[IF_NONE] = "none",
631
[IF_IDE] = "ide",
632
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *qmp_get_root_bs(const char *name, Error **errp)
633
return bs;
634
}
635
636
-static BlockBackend *qmp_get_blk(const char *blk_name, const char *qdev_id,
637
- Error **errp)
638
-{
639
- BlockBackend *blk;
640
-
641
- if (!blk_name == !qdev_id) {
642
- error_setg(errp, "Need exactly one of 'device' and 'id'");
643
- return NULL;
644
- }
645
-
646
- if (qdev_id) {
647
- blk = blk_by_qdev_id(qdev_id, errp);
648
- } else {
649
- blk = blk_by_name(blk_name);
650
- if (blk == NULL) {
651
- error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
652
- "Device '%s' not found", blk_name);
653
- }
654
- }
655
-
656
- return blk;
657
-}
658
-
659
void hmp_commit(Monitor *mon, const QDict *qdict)
660
{
661
const char *device = qdict_get_str(qdict, "device");
662
@@ -XXX,XX +XXX,XX @@ exit:
663
job_txn_unref(block_job_txn);
664
}
665
666
-void qmp_eject(bool has_device, const char *device,
667
- bool has_id, const char *id,
668
- bool has_force, bool force, Error **errp)
669
-{
670
- Error *local_err = NULL;
671
- int rc;
672
-
673
- if (!has_force) {
674
- force = false;
675
- }
676
-
677
- rc = do_open_tray(has_device ? device : NULL,
678
- has_id ? id : NULL,
679
- force, &local_err);
680
- if (rc && rc != -ENOSYS) {
681
- error_propagate(errp, local_err);
682
- return;
683
- }
684
- error_free(local_err);
685
-
686
- blockdev_remove_medium(has_device, device, has_id, id, errp);
687
-}
688
-
689
void qmp_block_passwd(bool has_device, const char *device,
690
bool has_node_name, const char *node_name,
691
const char *password, Error **errp)
692
@@ -XXX,XX +XXX,XX @@ void qmp_block_passwd(bool has_device, const char *device,
693
"Setting block passwords directly is no longer supported");
694
}
695
696
-/*
697
- * Attempt to open the tray of @device.
698
- * If @force, ignore its tray lock.
699
- * Else, if the tray is locked, don't open it, but ask the guest to open it.
700
- * On error, store an error through @errp and return -errno.
701
- * If @device does not exist, return -ENODEV.
702
- * If it has no removable media, return -ENOTSUP.
703
- * If it has no tray, return -ENOSYS.
704
- * If the guest was asked to open the tray, return -EINPROGRESS.
705
- * Else, return 0.
706
- */
707
-static int do_open_tray(const char *blk_name, const char *qdev_id,
708
- bool force, Error **errp)
709
-{
710
- BlockBackend *blk;
711
- const char *device = qdev_id ?: blk_name;
712
- bool locked;
713
-
714
- blk = qmp_get_blk(blk_name, qdev_id, errp);
715
- if (!blk) {
716
- return -ENODEV;
717
- }
718
-
719
- if (!blk_dev_has_removable_media(blk)) {
720
- error_setg(errp, "Device '%s' is not removable", device);
721
- return -ENOTSUP;
722
- }
723
-
724
- if (!blk_dev_has_tray(blk)) {
725
- error_setg(errp, "Device '%s' does not have a tray", device);
726
- return -ENOSYS;
727
- }
728
-
729
- if (blk_dev_is_tray_open(blk)) {
730
- return 0;
731
- }
732
-
733
- locked = blk_dev_is_medium_locked(blk);
734
- if (locked) {
735
- blk_dev_eject_request(blk, force);
736
- }
737
-
738
- if (!locked || force) {
739
- blk_dev_change_media_cb(blk, false, &error_abort);
740
- }
741
-
742
- if (locked && !force) {
743
- error_setg(errp, "Device '%s' is locked and force was not specified, "
744
- "wait for tray to open and try again", device);
745
- return -EINPROGRESS;
746
- }
747
-
748
- return 0;
749
-}
750
-
751
-void qmp_blockdev_open_tray(bool has_device, const char *device,
752
- bool has_id, const char *id,
753
- bool has_force, bool force,
754
- Error **errp)
755
-{
756
- Error *local_err = NULL;
757
- int rc;
758
-
759
- if (!has_force) {
760
- force = false;
761
- }
762
- rc = do_open_tray(has_device ? device : NULL,
763
- has_id ? id : NULL,
764
- force, &local_err);
765
- if (rc && rc != -ENOSYS && rc != -EINPROGRESS) {
766
- error_propagate(errp, local_err);
767
- return;
768
- }
769
- error_free(local_err);
770
-}
771
-
772
-void qmp_blockdev_close_tray(bool has_device, const char *device,
773
- bool has_id, const char *id,
774
- Error **errp)
775
-{
776
- BlockBackend *blk;
777
- Error *local_err = NULL;
778
-
779
- device = has_device ? device : NULL;
780
- id = has_id ? id : NULL;
781
-
782
- blk = qmp_get_blk(device, id, errp);
783
- if (!blk) {
784
- return;
785
- }
786
-
787
- if (!blk_dev_has_removable_media(blk)) {
788
- error_setg(errp, "Device '%s' is not removable", device ?: id);
789
- return;
790
- }
791
-
792
- if (!blk_dev_has_tray(blk)) {
793
- /* Ignore this command on tray-less devices */
794
- return;
795
- }
796
-
797
- if (!blk_dev_is_tray_open(blk)) {
798
- return;
799
- }
800
-
801
- blk_dev_change_media_cb(blk, true, &local_err);
802
- if (local_err) {
803
- error_propagate(errp, local_err);
804
- return;
805
- }
806
-}
807
-
808
-static void blockdev_remove_medium(bool has_device, const char *device,
809
- bool has_id, const char *id, Error **errp)
810
-{
811
- BlockBackend *blk;
812
- BlockDriverState *bs;
813
- AioContext *aio_context;
814
- bool has_attached_device;
815
-
816
- device = has_device ? device : NULL;
817
- id = has_id ? id : NULL;
818
-
819
- blk = qmp_get_blk(device, id, errp);
820
- if (!blk) {
821
- return;
822
- }
823
-
824
- /* For BBs without a device, we can exchange the BDS tree at will */
825
- has_attached_device = blk_get_attached_dev(blk);
826
-
827
- if (has_attached_device && !blk_dev_has_removable_media(blk)) {
828
- error_setg(errp, "Device '%s' is not removable", device ?: id);
829
- return;
830
- }
831
-
832
- if (has_attached_device && blk_dev_has_tray(blk) &&
833
- !blk_dev_is_tray_open(blk))
834
- {
835
- error_setg(errp, "Tray of device '%s' is not open", device ?: id);
836
- return;
837
- }
838
-
839
- bs = blk_bs(blk);
840
- if (!bs) {
841
- return;
842
- }
843
-
844
- aio_context = bdrv_get_aio_context(bs);
845
- aio_context_acquire(aio_context);
846
-
847
- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
848
- goto out;
849
- }
850
-
851
- blk_remove_bs(blk);
852
-
853
- if (!blk_dev_has_tray(blk)) {
854
- /* For tray-less devices, blockdev-open-tray is a no-op (or may not be
855
- * called at all); therefore, the medium needs to be ejected here.
856
- * Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load
857
- * value passed here (i.e. false). */
858
- blk_dev_change_media_cb(blk, false, &error_abort);
859
- }
860
-
861
-out:
862
- aio_context_release(aio_context);
863
-}
864
-
865
-void qmp_blockdev_remove_medium(const char *id, Error **errp)
866
-{
867
- blockdev_remove_medium(false, NULL, true, id, errp);
868
-}
869
-
870
-static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
871
- BlockDriverState *bs, Error **errp)
872
-{
873
- Error *local_err = NULL;
874
- bool has_device;
875
- int ret;
876
-
877
- /* For BBs without a device, we can exchange the BDS tree at will */
878
- has_device = blk_get_attached_dev(blk);
879
-
880
- if (has_device && !blk_dev_has_removable_media(blk)) {
881
- error_setg(errp, "Device is not removable");
882
- return;
883
- }
884
-
885
- if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) {
886
- error_setg(errp, "Tray of the device is not open");
887
- return;
888
- }
889
-
890
- if (blk_bs(blk)) {
891
- error_setg(errp, "There already is a medium in the device");
892
- return;
893
- }
894
-
895
- ret = blk_insert_bs(blk, bs, errp);
896
- if (ret < 0) {
897
- return;
898
- }
899
-
900
- if (!blk_dev_has_tray(blk)) {
901
- /* For tray-less devices, blockdev-close-tray is a no-op (or may not be
902
- * called at all); therefore, the medium needs to be pushed into the
903
- * slot here.
904
- * Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load
905
- * value passed here (i.e. true). */
906
- blk_dev_change_media_cb(blk, true, &local_err);
907
- if (local_err) {
908
- error_propagate(errp, local_err);
909
- blk_remove_bs(blk);
910
- return;
911
- }
912
- }
913
-}
914
-
915
-static void blockdev_insert_medium(bool has_device, const char *device,
916
- bool has_id, const char *id,
917
- const char *node_name, Error **errp)
918
-{
919
- BlockBackend *blk;
920
- BlockDriverState *bs;
921
-
922
- blk = qmp_get_blk(has_device ? device : NULL,
923
- has_id ? id : NULL,
924
- errp);
925
- if (!blk) {
926
- return;
927
- }
928
-
929
- bs = bdrv_find_node(node_name);
930
- if (!bs) {
931
- error_setg(errp, "Node '%s' not found", node_name);
932
- return;
933
- }
934
-
935
- if (bdrv_has_blk(bs)) {
936
- error_setg(errp, "Node '%s' is already in use", node_name);
937
- return;
938
- }
939
-
940
- qmp_blockdev_insert_anon_medium(blk, bs, errp);
941
-}
942
-
943
-void qmp_blockdev_insert_medium(const char *id, const char *node_name,
944
- Error **errp)
945
-{
946
- blockdev_insert_medium(false, NULL, true, id, node_name, errp);
947
-}
948
-
949
-void qmp_blockdev_change_medium(bool has_device, const char *device,
950
- bool has_id, const char *id,
951
- const char *filename,
952
- bool has_format, const char *format,
953
- bool has_read_only,
954
- BlockdevChangeReadOnlyMode read_only,
955
- Error **errp)
956
-{
957
- BlockBackend *blk;
958
- BlockDriverState *medium_bs = NULL;
959
- int bdrv_flags;
960
- bool detect_zeroes;
961
- int rc;
962
- QDict *options = NULL;
963
- Error *err = NULL;
964
-
965
- blk = qmp_get_blk(has_device ? device : NULL,
966
- has_id ? id : NULL,
967
- errp);
968
- if (!blk) {
969
- goto fail;
970
- }
971
-
972
- if (blk_bs(blk)) {
973
- blk_update_root_state(blk);
974
- }
975
-
976
- bdrv_flags = blk_get_open_flags_from_root_state(blk);
977
- bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
978
- BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
979
-
980
- if (!has_read_only) {
981
- read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
982
- }
983
-
984
- switch (read_only) {
985
- case BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN:
986
- break;
987
-
988
- case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_ONLY:
989
- bdrv_flags &= ~BDRV_O_RDWR;
990
- break;
991
-
992
- case BLOCKDEV_CHANGE_READ_ONLY_MODE_READ_WRITE:
993
- bdrv_flags |= BDRV_O_RDWR;
994
- break;
995
-
996
- default:
997
- abort();
998
- }
999
-
1000
- options = qdict_new();
1001
- detect_zeroes = blk_get_detect_zeroes_from_root_state(blk);
1002
- qdict_put_str(options, "detect-zeroes", detect_zeroes ? "on" : "off");
1003
-
1004
- if (has_format) {
1005
- qdict_put_str(options, "driver", format);
1006
- }
1007
-
1008
- medium_bs = bdrv_open(filename, NULL, options, bdrv_flags, errp);
1009
- if (!medium_bs) {
1010
- goto fail;
1011
- }
1012
-
1013
- rc = do_open_tray(has_device ? device : NULL,
1014
- has_id ? id : NULL,
1015
- false, &err);
1016
- if (rc && rc != -ENOSYS) {
1017
- error_propagate(errp, err);
1018
- goto fail;
1019
- }
1020
- error_free(err);
1021
- err = NULL;
1022
-
1023
- blockdev_remove_medium(has_device, device, has_id, id, &err);
1024
- if (err) {
1025
- error_propagate(errp, err);
1026
- goto fail;
1027
- }
1028
-
1029
- qmp_blockdev_insert_anon_medium(blk, medium_bs, &err);
1030
- if (err) {
1031
- error_propagate(errp, err);
1032
- goto fail;
1033
- }
1034
-
1035
- qmp_blockdev_close_tray(has_device, device, has_id, id, errp);
1036
-
1037
-fail:
1038
- /* If the medium has been inserted, the device has its own reference, so
1039
- * ours must be relinquished; and if it has not been inserted successfully,
1040
- * the reference must be relinquished anyway */
1041
- bdrv_unref(medium_bs);
1042
-}
1043
-
1044
-/* throttling disk I/O limits */
1045
-void qmp_block_set_io_throttle(BlockIOThrottle *arg, Error **errp)
1046
-{
1047
- ThrottleConfig cfg;
1048
- BlockDriverState *bs;
1049
- BlockBackend *blk;
1050
- AioContext *aio_context;
1051
-
1052
- blk = qmp_get_blk(arg->has_device ? arg->device : NULL,
1053
- arg->has_id ? arg->id : NULL,
1054
- errp);
1055
- if (!blk) {
1056
- return;
1057
- }
1058
-
1059
- aio_context = blk_get_aio_context(blk);
1060
- aio_context_acquire(aio_context);
1061
-
1062
- bs = blk_bs(blk);
1063
- if (!bs) {
1064
- error_setg(errp, "Device has no medium");
1065
- goto out;
1066
- }
1067
-
1068
- throttle_config_init(&cfg);
1069
- cfg.buckets[THROTTLE_BPS_TOTAL].avg = arg->bps;
1070
- cfg.buckets[THROTTLE_BPS_READ].avg = arg->bps_rd;
1071
- cfg.buckets[THROTTLE_BPS_WRITE].avg = arg->bps_wr;
1072
-
1073
- cfg.buckets[THROTTLE_OPS_TOTAL].avg = arg->iops;
1074
- cfg.buckets[THROTTLE_OPS_READ].avg = arg->iops_rd;
1075
- cfg.buckets[THROTTLE_OPS_WRITE].avg = arg->iops_wr;
1076
-
1077
- if (arg->has_bps_max) {
1078
- cfg.buckets[THROTTLE_BPS_TOTAL].max = arg->bps_max;
1079
- }
1080
- if (arg->has_bps_rd_max) {
1081
- cfg.buckets[THROTTLE_BPS_READ].max = arg->bps_rd_max;
1082
- }
1083
- if (arg->has_bps_wr_max) {
1084
- cfg.buckets[THROTTLE_BPS_WRITE].max = arg->bps_wr_max;
1085
- }
1086
- if (arg->has_iops_max) {
1087
- cfg.buckets[THROTTLE_OPS_TOTAL].max = arg->iops_max;
1088
- }
1089
- if (arg->has_iops_rd_max) {
1090
- cfg.buckets[THROTTLE_OPS_READ].max = arg->iops_rd_max;
1091
- }
1092
- if (arg->has_iops_wr_max) {
1093
- cfg.buckets[THROTTLE_OPS_WRITE].max = arg->iops_wr_max;
1094
- }
1095
-
1096
- if (arg->has_bps_max_length) {
1097
- cfg.buckets[THROTTLE_BPS_TOTAL].burst_length = arg->bps_max_length;
1098
- }
1099
- if (arg->has_bps_rd_max_length) {
1100
- cfg.buckets[THROTTLE_BPS_READ].burst_length = arg->bps_rd_max_length;
1101
- }
1102
- if (arg->has_bps_wr_max_length) {
1103
- cfg.buckets[THROTTLE_BPS_WRITE].burst_length = arg->bps_wr_max_length;
1104
- }
1105
- if (arg->has_iops_max_length) {
1106
- cfg.buckets[THROTTLE_OPS_TOTAL].burst_length = arg->iops_max_length;
1107
- }
1108
- if (arg->has_iops_rd_max_length) {
1109
- cfg.buckets[THROTTLE_OPS_READ].burst_length = arg->iops_rd_max_length;
1110
- }
1111
- if (arg->has_iops_wr_max_length) {
1112
- cfg.buckets[THROTTLE_OPS_WRITE].burst_length = arg->iops_wr_max_length;
1113
- }
1114
-
1115
- if (arg->has_iops_size) {
1116
- cfg.op_size = arg->iops_size;
1117
- }
1118
-
1119
- if (!throttle_is_valid(&cfg, errp)) {
1120
- goto out;
1121
- }
1122
-
1123
- if (throttle_enabled(&cfg)) {
1124
- /* Enable I/O limits if they're not enabled yet, otherwise
1125
- * just update the throttling group. */
1126
- if (!blk_get_public(blk)->throttle_group_member.throttle_state) {
1127
- blk_io_limits_enable(blk,
1128
- arg->has_group ? arg->group :
1129
- arg->has_device ? arg->device :
1130
- arg->id);
1131
- } else if (arg->has_group) {
1132
- blk_io_limits_update_group(blk, arg->group);
1133
- }
1134
- /* Set the new throttling configuration */
1135
- blk_set_io_limits(blk, &cfg);
1136
- } else if (blk_get_public(blk)->throttle_group_member.throttle_state) {
1137
- /* If all throttling settings are set to 0, disable I/O limits */
1138
- blk_io_limits_disable(blk);
1139
- }
1140
-
1141
-out:
1142
- aio_context_release(aio_context);
1143
-}
1144
-
1145
void qmp_block_dirty_bitmap_add(const char *node, const char *name,
1146
bool has_granularity, uint32_t granularity,
1147
bool has_persistent, bool persistent,
1148
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
1149
aio_context_release(old_context);
1150
}
1151
1152
-void qmp_block_latency_histogram_set(
1153
- const char *id,
1154
- bool has_boundaries, uint64List *boundaries,
1155
- bool has_boundaries_read, uint64List *boundaries_read,
1156
- bool has_boundaries_write, uint64List *boundaries_write,
1157
- bool has_boundaries_flush, uint64List *boundaries_flush,
1158
- Error **errp)
1159
-{
1160
- BlockBackend *blk = qmp_get_blk(NULL, id, errp);
1161
- BlockAcctStats *stats;
1162
- int ret;
1163
-
1164
- if (!blk) {
1165
- return;
1166
- }
1167
-
1168
- stats = blk_get_stats(blk);
1169
-
1170
- if (!has_boundaries && !has_boundaries_read && !has_boundaries_write &&
1171
- !has_boundaries_flush)
1172
- {
1173
- block_latency_histograms_clear(stats);
1174
- return;
1175
- }
1176
-
1177
- if (has_boundaries || has_boundaries_read) {
1178
- ret = block_latency_histogram_set(
1179
- stats, BLOCK_ACCT_READ,
1180
- has_boundaries_read ? boundaries_read : boundaries);
1181
- if (ret) {
1182
- error_setg(errp, "Device '%s' set read boundaries fail", id);
1183
- return;
1184
- }
1185
- }
1186
-
1187
- if (has_boundaries || has_boundaries_write) {
1188
- ret = block_latency_histogram_set(
1189
- stats, BLOCK_ACCT_WRITE,
1190
- has_boundaries_write ? boundaries_write : boundaries);
1191
- if (ret) {
1192
- error_setg(errp, "Device '%s' set write boundaries fail", id);
1193
- return;
1194
- }
1195
- }
1196
-
1197
- if (has_boundaries || has_boundaries_flush) {
1198
- ret = block_latency_histogram_set(
1199
- stats, BLOCK_ACCT_FLUSH,
1200
- has_boundaries_flush ? boundaries_flush : boundaries);
1201
- if (ret) {
1202
- error_setg(errp, "Device '%s' set flush boundaries fail", id);
1203
- return;
1204
- }
1205
- }
1206
-}
1207
-
1208
QemuOptsList qemu_common_drive_opts = {
1209
.name = "drive",
1210
.head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
1211
diff --git a/block/Makefile.objs b/block/Makefile.objs
44
index XXXXXXX..XXXXXXX 100644
1212
index XXXXXXX..XXXXXXX 100644
45
--- a/tests/qemu-iotests/051.pc.out
1213
--- a/block/Makefile.objs
46
+++ b/tests/qemu-iotests/051.pc.out
1214
+++ b/block/Makefile.objs
47
@@ -XXX,XX +XXX,XX @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.f
1215
@@ -XXX,XX +XXX,XX @@ block-obj-y += filter-compress.o
48
1216
49
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
1217
common-obj-y += stream.o
50
1218
51
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
1219
+common-obj-y += qapi-sysemu.o
52
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
1220
+
53
QEMU X.Y.Z monitor - type 'help' for more information
1221
nfs.o-libs := $(LIBNFS_LIBS)
54
(qemu) quit
1222
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
1223
iscsi.o-libs := $(LIBISCSI_LIBS)
55
--
1224
--
56
2.13.6
1225
2.20.1
57
1226
58
1227
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
block-core is for everything that isn't related to the system emulator.
2
Internal snapshots, the NBD server and quorum events make sense in the
3
tools, too, so move them to block-core.
2
4
3
vmdk cannot work with anything but vmdk backing files, so make the
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
backing file be the same format as the overlay.
6
Message-Id: <20200224143008.13362-5-kwolf@redhat.com>
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
qapi/block-core.json | 283 ++++++++++++++++++++++++++++++++++++++++++
11
qapi/block.json | 284 -------------------------------------------
12
2 files changed, 283 insertions(+), 284 deletions(-)
5
13
6
Reported-by: John Snow <jsnow@redhat.com>
14
diff --git a/qapi/block-core.json b/qapi/block-core.json
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20171123020832.8165-11-mreitz@redhat.com
9
Reviewed-by: John Snow <jsnow@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
tests/qemu-iotests/020 | 9 ++++++---
14
tests/qemu-iotests/020.out | 6 ++++--
15
2 files changed, 10 insertions(+), 5 deletions(-)
16
17
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/020
20
+++ b/tests/qemu-iotests/020
21
@@ -XXX,XX +XXX,XX @@ echo
22
echo 'Testing failing commit'
23
echo
24
25
+TEST_IMG="$TEST_IMG.base" _make_test_img 1M
26
+
27
# Create an image with a null backing file to which committing will fail (with
28
# ENOSPC so we can distinguish the result from some generic EIO which may be
29
# generated anywhere in the block layer)
30
-_make_test_img -b "json:{'driver': 'raw',
31
+_make_test_img -b "json:{'driver': '$IMGFMT',
32
'file': {
33
'driver': 'blkdebug',
34
'inject-error': [{
35
@@ -XXX,XX +XXX,XX @@ _make_test_img -b "json:{'driver': 'raw',
36
'once': true
37
}],
38
'image': {
39
- 'driver': 'null-co'
40
+ 'driver': 'file',
41
+ 'filename': '$TEST_IMG.base'
42
}}}"
43
44
# Just write anything so committing will not be a no-op
45
$QEMU_IO -c 'writev 0 64k' "$TEST_IMG" | _filter_qemu_io
46
47
$QEMU_IMG commit "$TEST_IMG"
48
-_cleanup_test_img
49
+_cleanup
50
51
# success, all done
52
echo "*** done"
53
diff --git a/tests/qemu-iotests/020.out b/tests/qemu-iotests/020.out
54
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
55
--- a/tests/qemu-iotests/020.out
16
--- a/qapi/block-core.json
56
+++ b/tests/qemu-iotests/020.out
17
+++ b/qapi/block-core.json
57
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
18
@@ -XXX,XX +XXX,XX @@
58
19
'data' : { 'node-name': 'str',
59
Testing failing commit
20
'iothread': 'StrOrNull',
60
21
'*force': 'bool' } }
61
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=json:{'driver': 'raw',,
22
+
62
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=1048576
23
+##
63
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=json:{'driver': 'IMGFMT',,
24
+# @nbd-server-start:
64
'file': {
25
+#
65
'driver': 'blkdebug',,
26
+# Start an NBD server listening on the given host and port. Block
66
'inject-error': [{
27
+# devices can then be exported using @nbd-server-add. The NBD
67
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=json:{'d
28
+# server will present them as named exports; for example, another
68
'once': true
29
+# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
69
}],,
30
+#
70
'image': {
31
+# @addr: Address on which to listen.
71
- 'driver': 'null-co'
32
+# @tls-creds: ID of the TLS credentials object (since 2.6).
72
+ 'driver': 'file',,
33
+# @tls-authz: ID of the QAuthZ authorization object used to validate
73
+ 'filename': 'TEST_DIR/t.IMGFMT.base'
34
+# the client's x509 distinguished name. This object is
74
}}}
35
+# is only resolved at time of use, so can be deleted and
75
wrote 65536/65536 bytes at offset 0
36
+# recreated on the fly while the NBD server is active.
76
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
37
+# If missing, it will default to denying access (since 4.0).
38
+#
39
+# Returns: error if the server is already running.
40
+#
41
+# Since: 1.3.0
42
+##
43
+{ 'command': 'nbd-server-start',
44
+ 'data': { 'addr': 'SocketAddressLegacy',
45
+ '*tls-creds': 'str',
46
+ '*tls-authz': 'str'} }
47
+
48
+##
49
+# @nbd-server-add:
50
+#
51
+# Export a block node to QEMU's embedded NBD server.
52
+#
53
+# @device: The device name or node name of the node to be exported
54
+#
55
+# @name: Export name. If unspecified, the @device parameter is used as the
56
+# export name. (Since 2.12)
57
+#
58
+# @description: Free-form description of the export, up to 4096 bytes.
59
+# (Since 5.0)
60
+#
61
+# @writable: Whether clients should be able to write to the device via the
62
+# NBD connection (default false).
63
+#
64
+# @bitmap: Also export the dirty bitmap reachable from @device, so the
65
+# NBD client can use NBD_OPT_SET_META_CONTEXT with
66
+# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
67
+#
68
+# Returns: error if the server is not running, or export with the same name
69
+# already exists.
70
+#
71
+# Since: 1.3.0
72
+##
73
+{ 'command': 'nbd-server-add',
74
+ 'data': {'device': 'str', '*name': 'str', '*description': 'str',
75
+ '*writable': 'bool', '*bitmap': 'str' } }
76
+
77
+##
78
+# @NbdServerRemoveMode:
79
+#
80
+# Mode for removing an NBD export.
81
+#
82
+# @safe: Remove export if there are no existing connections, fail otherwise.
83
+#
84
+# @hard: Drop all connections immediately and remove export.
85
+#
86
+# Potential additional modes to be added in the future:
87
+#
88
+# hide: Just hide export from new clients, leave existing connections as is.
89
+# Remove export after all clients are disconnected.
90
+#
91
+# soft: Hide export from new clients, answer with ESHUTDOWN for all further
92
+# requests from existing clients.
93
+#
94
+# Since: 2.12
95
+##
96
+{'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']}
97
+
98
+##
99
+# @nbd-server-remove:
100
+#
101
+# Remove NBD export by name.
102
+#
103
+# @name: Export name.
104
+#
105
+# @mode: Mode of command operation. See @NbdServerRemoveMode description.
106
+# Default is 'safe'.
107
+#
108
+# Returns: error if
109
+# - the server is not running
110
+# - export is not found
111
+# - mode is 'safe' and there are existing connections
112
+#
113
+# Since: 2.12
114
+##
115
+{ 'command': 'nbd-server-remove',
116
+ 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} }
117
+
118
+##
119
+# @nbd-server-stop:
120
+#
121
+# Stop QEMU's embedded NBD server, and unregister all devices previously
122
+# added via @nbd-server-add.
123
+#
124
+# Since: 1.3.0
125
+##
126
+{ 'command': 'nbd-server-stop' }
127
+
128
+##
129
+# @QuorumOpType:
130
+#
131
+# An enumeration of the quorum operation types
132
+#
133
+# @read: read operation
134
+#
135
+# @write: write operation
136
+#
137
+# @flush: flush operation
138
+#
139
+# Since: 2.6
140
+##
141
+{ 'enum': 'QuorumOpType',
142
+ 'data': [ 'read', 'write', 'flush' ] }
143
+
144
+##
145
+# @QUORUM_FAILURE:
146
+#
147
+# Emitted by the Quorum block driver if it fails to establish a quorum
148
+#
149
+# @reference: device name if defined else node name
150
+#
151
+# @sector-num: number of the first sector of the failed read operation
152
+#
153
+# @sectors-count: failed read operation sector count
154
+#
155
+# Note: This event is rate-limited.
156
+#
157
+# Since: 2.0
158
+#
159
+# Example:
160
+#
161
+# <- { "event": "QUORUM_FAILURE",
162
+# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
163
+# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
164
+#
165
+##
166
+{ 'event': 'QUORUM_FAILURE',
167
+ 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
168
+
169
+##
170
+# @QUORUM_REPORT_BAD:
171
+#
172
+# Emitted to report a corruption of a Quorum file
173
+#
174
+# @type: quorum operation type (Since 2.6)
175
+#
176
+# @error: error message. Only present on failure. This field
177
+# contains a human-readable error message. There are no semantics other
178
+# than that the block layer reported an error and clients should not
179
+# try to interpret the error string.
180
+#
181
+# @node-name: the graph node name of the block driver state
182
+#
183
+# @sector-num: number of the first sector of the failed read operation
184
+#
185
+# @sectors-count: failed read operation sector count
186
+#
187
+# Note: This event is rate-limited.
188
+#
189
+# Since: 2.0
190
+#
191
+# Example:
192
+#
193
+# 1. Read operation
194
+#
195
+# { "event": "QUORUM_REPORT_BAD",
196
+# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
197
+# "type": "read" },
198
+# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
199
+#
200
+# 2. Flush operation
201
+#
202
+# { "event": "QUORUM_REPORT_BAD",
203
+# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
204
+# "type": "flush", "error": "Broken pipe" },
205
+# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } }
206
+#
207
+##
208
+{ 'event': 'QUORUM_REPORT_BAD',
209
+ 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
210
+ 'sector-num': 'int', 'sectors-count': 'int' } }
211
+
212
+##
213
+# @BlockdevSnapshotInternal:
214
+#
215
+# @device: the device name or node-name of a root node to generate the snapshot
216
+# from
217
+#
218
+# @name: the name of the internal snapshot to be created
219
+#
220
+# Notes: In transaction, if @name is empty, or any snapshot matching @name
221
+# exists, the operation will fail. Only some image formats support it,
222
+# for example, qcow2, rbd, and sheepdog.
223
+#
224
+# Since: 1.7
225
+##
226
+{ 'struct': 'BlockdevSnapshotInternal',
227
+ 'data': { 'device': 'str', 'name': 'str' } }
228
+
229
+##
230
+# @blockdev-snapshot-internal-sync:
231
+#
232
+# Synchronously take an internal snapshot of a block device, when the
233
+# format of the image used supports it. If the name is an empty
234
+# string, or a snapshot with name already exists, the operation will
235
+# fail.
236
+#
237
+# For the arguments, see the documentation of BlockdevSnapshotInternal.
238
+#
239
+# Returns: - nothing on success
240
+# - If @device is not a valid block device, GenericError
241
+# - If any snapshot matching @name exists, or @name is empty,
242
+# GenericError
243
+# - If the format of the image used does not support it,
244
+# BlockFormatFeatureNotSupported
245
+#
246
+# Since: 1.7
247
+#
248
+# Example:
249
+#
250
+# -> { "execute": "blockdev-snapshot-internal-sync",
251
+# "arguments": { "device": "ide-hd0",
252
+# "name": "snapshot0" }
253
+# }
254
+# <- { "return": {} }
255
+#
256
+##
257
+{ 'command': 'blockdev-snapshot-internal-sync',
258
+ 'data': 'BlockdevSnapshotInternal' }
259
+
260
+##
261
+# @blockdev-snapshot-delete-internal-sync:
262
+#
263
+# Synchronously delete an internal snapshot of a block device, when the format
264
+# of the image used support it. The snapshot is identified by name or id or
265
+# both. One of the name or id is required. Return SnapshotInfo for the
266
+# successfully deleted snapshot.
267
+#
268
+# @device: the device name or node-name of a root node to delete the snapshot
269
+# from
270
+#
271
+# @id: optional the snapshot's ID to be deleted
272
+#
273
+# @name: optional the snapshot's name to be deleted
274
+#
275
+# Returns: - SnapshotInfo on success
276
+# - If @device is not a valid block device, GenericError
277
+# - If snapshot not found, GenericError
278
+# - If the format of the image used does not support it,
279
+# BlockFormatFeatureNotSupported
280
+# - If @id and @name are both not specified, GenericError
281
+#
282
+# Since: 1.7
283
+#
284
+# Example:
285
+#
286
+# -> { "execute": "blockdev-snapshot-delete-internal-sync",
287
+# "arguments": { "device": "ide-hd0",
288
+# "name": "snapshot0" }
289
+# }
290
+# <- { "return": {
291
+# "id": "1",
292
+# "name": "snapshot0",
293
+# "vm-state-size": 0,
294
+# "date-sec": 1000012,
295
+# "date-nsec": 10,
296
+# "vm-clock-sec": 100,
297
+# "vm-clock-nsec": 20
298
+# }
299
+# }
300
+#
301
+##
302
+{ 'command': 'blockdev-snapshot-delete-internal-sync',
303
+ 'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
304
+ 'returns': 'SnapshotInfo' }
305
diff --git a/qapi/block.json b/qapi/block.json
306
index XXXXXXX..XXXXXXX 100644
307
--- a/qapi/block.json
308
+++ b/qapi/block.json
309
@@ -XXX,XX +XXX,XX @@
310
{ 'enum': 'FloppyDriveType',
311
'data': ['144', '288', '120', 'none', 'auto']}
312
313
-##
314
-# @BlockdevSnapshotInternal:
315
-#
316
-# @device: the device name or node-name of a root node to generate the snapshot
317
-# from
318
-#
319
-# @name: the name of the internal snapshot to be created
320
-#
321
-# Notes: In transaction, if @name is empty, or any snapshot matching @name
322
-# exists, the operation will fail. Only some image formats support it,
323
-# for example, qcow2, rbd, and sheepdog.
324
-#
325
-# Since: 1.7
326
-##
327
-{ 'struct': 'BlockdevSnapshotInternal',
328
- 'data': { 'device': 'str', 'name': 'str' } }
329
-
330
##
331
# @PRManagerInfo:
332
#
333
@@ -XXX,XX +XXX,XX @@
334
{ 'command': 'query-pr-managers', 'returns': ['PRManagerInfo'],
335
'allow-preconfig': true }
336
337
-
338
-##
339
-# @blockdev-snapshot-internal-sync:
340
-#
341
-# Synchronously take an internal snapshot of a block device, when the
342
-# format of the image used supports it. If the name is an empty
343
-# string, or a snapshot with name already exists, the operation will
344
-# fail.
345
-#
346
-# For the arguments, see the documentation of BlockdevSnapshotInternal.
347
-#
348
-# Returns: - nothing on success
349
-# - If @device is not a valid block device, GenericError
350
-# - If any snapshot matching @name exists, or @name is empty,
351
-# GenericError
352
-# - If the format of the image used does not support it,
353
-# BlockFormatFeatureNotSupported
354
-#
355
-# Since: 1.7
356
-#
357
-# Example:
358
-#
359
-# -> { "execute": "blockdev-snapshot-internal-sync",
360
-# "arguments": { "device": "ide-hd0",
361
-# "name": "snapshot0" }
362
-# }
363
-# <- { "return": {} }
364
-#
365
-##
366
-{ 'command': 'blockdev-snapshot-internal-sync',
367
- 'data': 'BlockdevSnapshotInternal' }
368
-
369
-##
370
-# @blockdev-snapshot-delete-internal-sync:
371
-#
372
-# Synchronously delete an internal snapshot of a block device, when the format
373
-# of the image used support it. The snapshot is identified by name or id or
374
-# both. One of the name or id is required. Return SnapshotInfo for the
375
-# successfully deleted snapshot.
376
-#
377
-# @device: the device name or node-name of a root node to delete the snapshot
378
-# from
379
-#
380
-# @id: optional the snapshot's ID to be deleted
381
-#
382
-# @name: optional the snapshot's name to be deleted
383
-#
384
-# Returns: - SnapshotInfo on success
385
-# - If @device is not a valid block device, GenericError
386
-# - If snapshot not found, GenericError
387
-# - If the format of the image used does not support it,
388
-# BlockFormatFeatureNotSupported
389
-# - If @id and @name are both not specified, GenericError
390
-#
391
-# Since: 1.7
392
-#
393
-# Example:
394
-#
395
-# -> { "execute": "blockdev-snapshot-delete-internal-sync",
396
-# "arguments": { "device": "ide-hd0",
397
-# "name": "snapshot0" }
398
-# }
399
-# <- { "return": {
400
-# "id": "1",
401
-# "name": "snapshot0",
402
-# "vm-state-size": 0,
403
-# "date-sec": 1000012,
404
-# "date-nsec": 10,
405
-# "vm-clock-sec": 100,
406
-# "vm-clock-nsec": 20
407
-# }
408
-# }
409
-#
410
-##
411
-{ 'command': 'blockdev-snapshot-delete-internal-sync',
412
- 'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
413
- 'returns': 'SnapshotInfo' }
414
-
415
##
416
# @eject:
417
#
418
@@ -XXX,XX +XXX,XX @@
419
'*id': 'str',
420
'*force': 'bool' } }
421
422
-##
423
-# @nbd-server-start:
424
-#
425
-# Start an NBD server listening on the given host and port. Block
426
-# devices can then be exported using @nbd-server-add. The NBD
427
-# server will present them as named exports; for example, another
428
-# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
429
-#
430
-# @addr: Address on which to listen.
431
-# @tls-creds: ID of the TLS credentials object (since 2.6).
432
-# @tls-authz: ID of the QAuthZ authorization object used to validate
433
-# the client's x509 distinguished name. This object is
434
-# is only resolved at time of use, so can be deleted and
435
-# recreated on the fly while the NBD server is active.
436
-# If missing, it will default to denying access (since 4.0).
437
-#
438
-# Returns: error if the server is already running.
439
-#
440
-# Since: 1.3.0
441
-##
442
-{ 'command': 'nbd-server-start',
443
- 'data': { 'addr': 'SocketAddressLegacy',
444
- '*tls-creds': 'str',
445
- '*tls-authz': 'str'} }
446
-
447
-##
448
-# @nbd-server-add:
449
-#
450
-# Export a block node to QEMU's embedded NBD server.
451
-#
452
-# @device: The device name or node name of the node to be exported
453
-#
454
-# @name: Export name. If unspecified, the @device parameter is used as the
455
-# export name. (Since 2.12)
456
-#
457
-# @description: Free-form description of the export, up to 4096 bytes.
458
-# (Since 5.0)
459
-#
460
-# @writable: Whether clients should be able to write to the device via the
461
-# NBD connection (default false).
462
-#
463
-# @bitmap: Also export the dirty bitmap reachable from @device, so the
464
-# NBD client can use NBD_OPT_SET_META_CONTEXT with
465
-# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
466
-#
467
-# Returns: error if the server is not running, or export with the same name
468
-# already exists.
469
-#
470
-# Since: 1.3.0
471
-##
472
-{ 'command': 'nbd-server-add',
473
- 'data': {'device': 'str', '*name': 'str', '*description': 'str',
474
- '*writable': 'bool', '*bitmap': 'str' } }
475
-
476
-##
477
-# @NbdServerRemoveMode:
478
-#
479
-# Mode for removing an NBD export.
480
-#
481
-# @safe: Remove export if there are no existing connections, fail otherwise.
482
-#
483
-# @hard: Drop all connections immediately and remove export.
484
-#
485
-# Potential additional modes to be added in the future:
486
-#
487
-# hide: Just hide export from new clients, leave existing connections as is.
488
-# Remove export after all clients are disconnected.
489
-#
490
-# soft: Hide export from new clients, answer with ESHUTDOWN for all further
491
-# requests from existing clients.
492
-#
493
-# Since: 2.12
494
-##
495
-{'enum': 'NbdServerRemoveMode', 'data': ['safe', 'hard']}
496
-
497
-##
498
-# @nbd-server-remove:
499
-#
500
-# Remove NBD export by name.
501
-#
502
-# @name: Export name.
503
-#
504
-# @mode: Mode of command operation. See @NbdServerRemoveMode description.
505
-# Default is 'safe'.
506
-#
507
-# Returns: error if
508
-# - the server is not running
509
-# - export is not found
510
-# - mode is 'safe' and there are existing connections
511
-#
512
-# Since: 2.12
513
-##
514
-{ 'command': 'nbd-server-remove',
515
- 'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} }
516
-
517
-##
518
-# @nbd-server-stop:
519
-#
520
-# Stop QEMU's embedded NBD server, and unregister all devices previously
521
-# added via @nbd-server-add.
522
-#
523
-# Since: 1.3.0
524
-##
525
-{ 'command': 'nbd-server-stop' }
526
-
527
##
528
# @DEVICE_TRAY_MOVED:
529
#
530
@@ -XXX,XX +XXX,XX @@
531
##
532
{ 'event': 'PR_MANAGER_STATUS_CHANGED',
533
'data': { 'id': 'str', 'connected': 'bool' } }
534
-
535
-##
536
-# @QuorumOpType:
537
-#
538
-# An enumeration of the quorum operation types
539
-#
540
-# @read: read operation
541
-#
542
-# @write: write operation
543
-#
544
-# @flush: flush operation
545
-#
546
-# Since: 2.6
547
-##
548
-{ 'enum': 'QuorumOpType',
549
- 'data': [ 'read', 'write', 'flush' ] }
550
-
551
-##
552
-# @QUORUM_FAILURE:
553
-#
554
-# Emitted by the Quorum block driver if it fails to establish a quorum
555
-#
556
-# @reference: device name if defined else node name
557
-#
558
-# @sector-num: number of the first sector of the failed read operation
559
-#
560
-# @sectors-count: failed read operation sector count
561
-#
562
-# Note: This event is rate-limited.
563
-#
564
-# Since: 2.0
565
-#
566
-# Example:
567
-#
568
-# <- { "event": "QUORUM_FAILURE",
569
-# "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
570
-# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
571
-#
572
-##
573
-{ 'event': 'QUORUM_FAILURE',
574
- 'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
575
-
576
-##
577
-# @QUORUM_REPORT_BAD:
578
-#
579
-# Emitted to report a corruption of a Quorum file
580
-#
581
-# @type: quorum operation type (Since 2.6)
582
-#
583
-# @error: error message. Only present on failure. This field
584
-# contains a human-readable error message. There are no semantics other
585
-# than that the block layer reported an error and clients should not
586
-# try to interpret the error string.
587
-#
588
-# @node-name: the graph node name of the block driver state
589
-#
590
-# @sector-num: number of the first sector of the failed read operation
591
-#
592
-# @sectors-count: failed read operation sector count
593
-#
594
-# Note: This event is rate-limited.
595
-#
596
-# Since: 2.0
597
-#
598
-# Example:
599
-#
600
-# 1. Read operation
601
-#
602
-# { "event": "QUORUM_REPORT_BAD",
603
-# "data": { "node-name": "node0", "sector-num": 345435, "sectors-count": 5,
604
-# "type": "read" },
605
-# "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
606
-#
607
-# 2. Flush operation
608
-#
609
-# { "event": "QUORUM_REPORT_BAD",
610
-# "data": { "node-name": "node0", "sector-num": 0, "sectors-count": 2097120,
611
-# "type": "flush", "error": "Broken pipe" },
612
-# "timestamp": { "seconds": 1456406829, "microseconds": 291763 } }
613
-#
614
-##
615
-{ 'event': 'QUORUM_REPORT_BAD',
616
- 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
617
- 'sector-num': 'int', 'sectors-count': 'int' } }
77
--
618
--
78
2.13.6
619
2.20.1
79
620
80
621
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
QMP commands that are related to the system emulator and don't make
2
sense in the context of tools such as qemu-storage-daemon should live in
3
qapi/block.json rather than qapi/block-core.json. Move them there.
2
4
3
This test does funny things like TEST_IMG="TEST_IMG.base" _make_test_img
5
The associated data types are actually also used in code shared with the
4
that usually only work with the file protocol. More specifically, they
6
tools, so they stay in block-core.json.
5
do not work with the most interesting non-file protocols, so we might as
6
well skip this for anything but file.
7
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20171123020832.8165-8-mreitz@redhat.com
9
Message-Id: <20200224143008.13362-6-kwolf@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
12
---
13
tests/qemu-iotests/020 | 8 +-------
13
qapi/block-core.json | 386 -------------------------------------------
14
1 file changed, 1 insertion(+), 7 deletions(-)
14
qapi/block.json | 386 +++++++++++++++++++++++++++++++++++++++++++
15
monitor/qmp-cmds.c | 2 +-
16
3 files changed, 387 insertions(+), 387 deletions(-)
15
17
16
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
18
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/020
20
--- a/qapi/block-core.json
19
+++ b/tests/qemu-iotests/020
21
+++ b/qapi/block-core.json
20
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
22
@@ -XXX,XX +XXX,XX @@
21
23
{ 'struct': 'BlockLatencyHistogramInfo',
22
# Any format supporting backing files
24
'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
23
_supported_fmt qcow qcow2 vmdk qed
25
24
-_supported_proto generic
26
-##
25
-_unsupported_proto vxhs
27
-# @block-latency-histogram-set:
26
+_supported_proto file
28
-#
27
_supported_os Linux
29
-# Manage read, write and flush latency histograms for the device.
28
_unsupported_imgopts "subformat=monolithicFlat" \
30
-#
29
"subformat=twoGbMaxExtentFlat" \
31
-# If only @id parameter is specified, remove all present latency histograms
30
"subformat=twoGbMaxExtentSparse"
32
-# for the device. Otherwise, add/reset some of (or all) latency histograms.
31
33
-#
32
-# NFS does not support bdrv_reopen_prepare thus qemu-img commit fails.
34
-# @id: The name or QOM path of the guest device.
33
-if [ "$IMGPROTO" = "nfs" ]; then
35
-#
34
- _notrun "image protocol $IMGPROTO does not support bdrv_commit"
36
-# @boundaries: list of interval boundary values (see description in
35
-fi
37
-# BlockLatencyHistogramInfo definition). If specified, all
36
-
38
-# latency histograms are removed, and empty ones created for all
37
TEST_OFFSETS="0 4294967296"
39
-# io types with intervals corresponding to @boundaries (except for
38
40
-# io types, for which specific boundaries are set through the
39
TEST_IMG_SAVE="$TEST_IMG"
41
-# following parameters).
42
-#
43
-# @boundaries-read: list of interval boundary values for read latency
44
-# histogram. If specified, old read latency histogram is
45
-# removed, and empty one created with intervals
46
-# corresponding to @boundaries-read. The parameter has higher
47
-# priority then @boundaries.
48
-#
49
-# @boundaries-write: list of interval boundary values for write latency
50
-# histogram.
51
-#
52
-# @boundaries-flush: list of interval boundary values for flush latency
53
-# histogram.
54
-#
55
-# Returns: error if device is not found or any boundary arrays are invalid.
56
-#
57
-# Since: 4.0
58
-#
59
-# Example: set new histograms for all io types with intervals
60
-# [0, 10), [10, 50), [50, 100), [100, +inf):
61
-#
62
-# -> { "execute": "block-latency-histogram-set",
63
-# "arguments": { "id": "drive0",
64
-# "boundaries": [10, 50, 100] } }
65
-# <- { "return": {} }
66
-#
67
-# Example: set new histogram only for write, other histograms will remain
68
-# not changed (or not created):
69
-#
70
-# -> { "execute": "block-latency-histogram-set",
71
-# "arguments": { "id": "drive0",
72
-# "boundaries-write": [10, 50, 100] } }
73
-# <- { "return": {} }
74
-#
75
-# Example: set new histograms with the following intervals:
76
-# read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
77
-# write: [0, 1000), [1000, 5000), [5000, +inf)
78
-#
79
-# -> { "execute": "block-latency-histogram-set",
80
-# "arguments": { "id": "drive0",
81
-# "boundaries": [10, 50, 100],
82
-# "boundaries-write": [1000, 5000] } }
83
-# <- { "return": {} }
84
-#
85
-# Example: remove all latency histograms:
86
-#
87
-# -> { "execute": "block-latency-histogram-set",
88
-# "arguments": { "id": "drive0" } }
89
-# <- { "return": {} }
90
-##
91
-{ 'command': 'block-latency-histogram-set',
92
- 'data': {'id': 'str',
93
- '*boundaries': ['uint64'],
94
- '*boundaries-read': ['uint64'],
95
- '*boundaries-write': ['uint64'],
96
- '*boundaries-flush': ['uint64'] } }
97
-
98
##
99
# @BlockInfo:
100
#
101
@@ -XXX,XX +XXX,XX @@
102
'*copy-mode': 'MirrorCopyMode',
103
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
104
105
-##
106
-# @block_set_io_throttle:
107
-#
108
-# Change I/O throttle limits for a block drive.
109
-#
110
-# Since QEMU 2.4, each device with I/O limits is member of a throttle
111
-# group.
112
-#
113
-# If two or more devices are members of the same group, the limits
114
-# will apply to the combined I/O of the whole group in a round-robin
115
-# fashion. Therefore, setting new I/O limits to a device will affect
116
-# the whole group.
117
-#
118
-# The name of the group can be specified using the 'group' parameter.
119
-# If the parameter is unset, it is assumed to be the current group of
120
-# that device. If it's not in any group yet, the name of the device
121
-# will be used as the name for its group.
122
-#
123
-# The 'group' parameter can also be used to move a device to a
124
-# different group. In this case the limits specified in the parameters
125
-# will be applied to the new group only.
126
-#
127
-# I/O limits can be disabled by setting all of them to 0. In this case
128
-# the device will be removed from its group and the rest of its
129
-# members will not be affected. The 'group' parameter is ignored.
130
-#
131
-# Returns: - Nothing on success
132
-# - If @device is not a valid block device, DeviceNotFound
133
-#
134
-# Since: 1.1
135
-#
136
-# Example:
137
-#
138
-# -> { "execute": "block_set_io_throttle",
139
-# "arguments": { "id": "virtio-blk-pci0/virtio-backend",
140
-# "bps": 0,
141
-# "bps_rd": 0,
142
-# "bps_wr": 0,
143
-# "iops": 512,
144
-# "iops_rd": 0,
145
-# "iops_wr": 0,
146
-# "bps_max": 0,
147
-# "bps_rd_max": 0,
148
-# "bps_wr_max": 0,
149
-# "iops_max": 0,
150
-# "iops_rd_max": 0,
151
-# "iops_wr_max": 0,
152
-# "bps_max_length": 0,
153
-# "iops_size": 0 } }
154
-# <- { "return": {} }
155
-#
156
-# -> { "execute": "block_set_io_throttle",
157
-# "arguments": { "id": "ide0-1-0",
158
-# "bps": 1000000,
159
-# "bps_rd": 0,
160
-# "bps_wr": 0,
161
-# "iops": 0,
162
-# "iops_rd": 0,
163
-# "iops_wr": 0,
164
-# "bps_max": 8000000,
165
-# "bps_rd_max": 0,
166
-# "bps_wr_max": 0,
167
-# "iops_max": 0,
168
-# "iops_rd_max": 0,
169
-# "iops_wr_max": 0,
170
-# "bps_max_length": 60,
171
-# "iops_size": 0 } }
172
-# <- { "return": {} }
173
-##
174
-{ 'command': 'block_set_io_throttle', 'boxed': true,
175
- 'data': 'BlockIOThrottle' }
176
-
177
##
178
# @BlockIOThrottle:
179
#
180
@@ -XXX,XX +XXX,XX @@
181
'data': { 'job-id': 'str',
182
'options': 'BlockdevCreateOptions' } }
183
184
-##
185
-# @blockdev-open-tray:
186
-#
187
-# Opens a block device's tray. If there is a block driver state tree inserted as
188
-# a medium, it will become inaccessible to the guest (but it will remain
189
-# associated to the block device, so closing the tray will make it accessible
190
-# again).
191
-#
192
-# If the tray was already open before, this will be a no-op.
193
-#
194
-# Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in
195
-# which no such event will be generated, these include:
196
-#
197
-# - if the guest has locked the tray, @force is false and the guest does not
198
-# respond to the eject request
199
-# - if the BlockBackend denoted by @device does not have a guest device attached
200
-# to it
201
-# - if the guest device does not have an actual tray
202
-#
203
-# @device: Block device name (deprecated, use @id instead)
204
-#
205
-# @id: The name or QOM path of the guest device (since: 2.8)
206
-#
207
-# @force: if false (the default), an eject request will be sent to
208
-# the guest if it has locked the tray (and the tray will not be opened
209
-# immediately); if true, the tray will be opened regardless of whether
210
-# it is locked
211
-#
212
-# Since: 2.5
213
-#
214
-# Example:
215
-#
216
-# -> { "execute": "blockdev-open-tray",
217
-# "arguments": { "id": "ide0-1-0" } }
218
-#
219
-# <- { "timestamp": { "seconds": 1418751016,
220
-# "microseconds": 716996 },
221
-# "event": "DEVICE_TRAY_MOVED",
222
-# "data": { "device": "ide1-cd0",
223
-# "id": "ide0-1-0",
224
-# "tray-open": true } }
225
-#
226
-# <- { "return": {} }
227
-#
228
-##
229
-{ 'command': 'blockdev-open-tray',
230
- 'data': { '*device': 'str',
231
- '*id': 'str',
232
- '*force': 'bool' } }
233
-
234
-##
235
-# @blockdev-close-tray:
236
-#
237
-# Closes a block device's tray. If there is a block driver state tree associated
238
-# with the block device (which is currently ejected), that tree will be loaded
239
-# as the medium.
240
-#
241
-# If the tray was already closed before, this will be a no-op.
242
-#
243
-# @device: Block device name (deprecated, use @id instead)
244
-#
245
-# @id: The name or QOM path of the guest device (since: 2.8)
246
-#
247
-# Since: 2.5
248
-#
249
-# Example:
250
-#
251
-# -> { "execute": "blockdev-close-tray",
252
-# "arguments": { "id": "ide0-1-0" } }
253
-#
254
-# <- { "timestamp": { "seconds": 1418751345,
255
-# "microseconds": 272147 },
256
-# "event": "DEVICE_TRAY_MOVED",
257
-# "data": { "device": "ide1-cd0",
258
-# "id": "ide0-1-0",
259
-# "tray-open": false } }
260
-#
261
-# <- { "return": {} }
262
-#
263
-##
264
-{ 'command': 'blockdev-close-tray',
265
- 'data': { '*device': 'str',
266
- '*id': 'str' } }
267
-
268
-##
269
-# @blockdev-remove-medium:
270
-#
271
-# Removes a medium (a block driver state tree) from a block device. That block
272
-# device's tray must currently be open (unless there is no attached guest
273
-# device).
274
-#
275
-# If the tray is open and there is no medium inserted, this will be a no-op.
276
-#
277
-# @id: The name or QOM path of the guest device
278
-#
279
-# Since: 2.12
280
-#
281
-# Example:
282
-#
283
-# -> { "execute": "blockdev-remove-medium",
284
-# "arguments": { "id": "ide0-1-0" } }
285
-#
286
-# <- { "error": { "class": "GenericError",
287
-# "desc": "Tray of device 'ide0-1-0' is not open" } }
288
-#
289
-# -> { "execute": "blockdev-open-tray",
290
-# "arguments": { "id": "ide0-1-0" } }
291
-#
292
-# <- { "timestamp": { "seconds": 1418751627,
293
-# "microseconds": 549958 },
294
-# "event": "DEVICE_TRAY_MOVED",
295
-# "data": { "device": "ide1-cd0",
296
-# "id": "ide0-1-0",
297
-# "tray-open": true } }
298
-#
299
-# <- { "return": {} }
300
-#
301
-# -> { "execute": "blockdev-remove-medium",
302
-# "arguments": { "id": "ide0-1-0" } }
303
-#
304
-# <- { "return": {} }
305
-#
306
-##
307
-{ 'command': 'blockdev-remove-medium',
308
- 'data': { 'id': 'str' } }
309
-
310
-##
311
-# @blockdev-insert-medium:
312
-#
313
-# Inserts a medium (a block driver state tree) into a block device. That block
314
-# device's tray must currently be open (unless there is no attached guest
315
-# device) and there must be no medium inserted already.
316
-#
317
-# @id: The name or QOM path of the guest device
318
-#
319
-# @node-name: name of a node in the block driver state graph
320
-#
321
-# Since: 2.12
322
-#
323
-# Example:
324
-#
325
-# -> { "execute": "blockdev-add",
326
-# "arguments": {
327
-# "node-name": "node0",
328
-# "driver": "raw",
329
-# "file": { "driver": "file",
330
-# "filename": "fedora.iso" } } }
331
-# <- { "return": {} }
332
-#
333
-# -> { "execute": "blockdev-insert-medium",
334
-# "arguments": { "id": "ide0-1-0",
335
-# "node-name": "node0" } }
336
-#
337
-# <- { "return": {} }
338
-#
339
-##
340
-{ 'command': 'blockdev-insert-medium',
341
- 'data': { 'id': 'str',
342
- 'node-name': 'str'} }
343
-
344
-
345
-##
346
-# @BlockdevChangeReadOnlyMode:
347
-#
348
-# Specifies the new read-only mode of a block device subject to the
349
-# @blockdev-change-medium command.
350
-#
351
-# @retain: Retains the current read-only mode
352
-#
353
-# @read-only: Makes the device read-only
354
-#
355
-# @read-write: Makes the device writable
356
-#
357
-# Since: 2.3
358
-#
359
-##
360
-{ 'enum': 'BlockdevChangeReadOnlyMode',
361
- 'data': ['retain', 'read-only', 'read-write'] }
362
-
363
-
364
-##
365
-# @blockdev-change-medium:
366
-#
367
-# Changes the medium inserted into a block device by ejecting the current medium
368
-# and loading a new image file which is inserted as the new medium (this command
369
-# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
370
-# and blockdev-close-tray).
371
-#
372
-# @device: Block device name (deprecated, use @id instead)
373
-#
374
-# @id: The name or QOM path of the guest device
375
-# (since: 2.8)
376
-#
377
-# @filename: filename of the new image to be loaded
378
-#
379
-# @format: format to open the new image with (defaults to
380
-# the probed format)
381
-#
382
-# @read-only-mode: change the read-only mode of the device; defaults
383
-# to 'retain'
384
-#
385
-# Since: 2.5
386
-#
387
-# Examples:
388
-#
389
-# 1. Change a removable medium
390
-#
391
-# -> { "execute": "blockdev-change-medium",
392
-# "arguments": { "id": "ide0-1-0",
393
-# "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
394
-# "format": "raw" } }
395
-# <- { "return": {} }
396
-#
397
-# 2. Load a read-only medium into a writable drive
398
-#
399
-# -> { "execute": "blockdev-change-medium",
400
-# "arguments": { "id": "floppyA",
401
-# "filename": "/srv/images/ro.img",
402
-# "format": "raw",
403
-# "read-only-mode": "retain" } }
404
-#
405
-# <- { "error":
406
-# { "class": "GenericError",
407
-# "desc": "Could not open '/srv/images/ro.img': Permission denied" } }
408
-#
409
-# -> { "execute": "blockdev-change-medium",
410
-# "arguments": { "id": "floppyA",
411
-# "filename": "/srv/images/ro.img",
412
-# "format": "raw",
413
-# "read-only-mode": "read-only" } }
414
-#
415
-# <- { "return": {} }
416
-#
417
-##
418
-{ 'command': 'blockdev-change-medium',
419
- 'data': { '*device': 'str',
420
- '*id': 'str',
421
- 'filename': 'str',
422
- '*format': 'str',
423
- '*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
424
-
425
-
426
##
427
# @BlockErrorAction:
428
#
429
diff --git a/qapi/block.json b/qapi/block.json
430
index XXXXXXX..XXXXXXX 100644
431
--- a/qapi/block.json
432
+++ b/qapi/block.json
433
@@ -XXX,XX +XXX,XX @@
434
'*id': 'str',
435
'*force': 'bool' } }
436
437
+##
438
+# @blockdev-open-tray:
439
+#
440
+# Opens a block device's tray. If there is a block driver state tree inserted as
441
+# a medium, it will become inaccessible to the guest (but it will remain
442
+# associated to the block device, so closing the tray will make it accessible
443
+# again).
444
+#
445
+# If the tray was already open before, this will be a no-op.
446
+#
447
+# Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in
448
+# which no such event will be generated, these include:
449
+#
450
+# - if the guest has locked the tray, @force is false and the guest does not
451
+# respond to the eject request
452
+# - if the BlockBackend denoted by @device does not have a guest device attached
453
+# to it
454
+# - if the guest device does not have an actual tray
455
+#
456
+# @device: Block device name (deprecated, use @id instead)
457
+#
458
+# @id: The name or QOM path of the guest device (since: 2.8)
459
+#
460
+# @force: if false (the default), an eject request will be sent to
461
+# the guest if it has locked the tray (and the tray will not be opened
462
+# immediately); if true, the tray will be opened regardless of whether
463
+# it is locked
464
+#
465
+# Since: 2.5
466
+#
467
+# Example:
468
+#
469
+# -> { "execute": "blockdev-open-tray",
470
+# "arguments": { "id": "ide0-1-0" } }
471
+#
472
+# <- { "timestamp": { "seconds": 1418751016,
473
+# "microseconds": 716996 },
474
+# "event": "DEVICE_TRAY_MOVED",
475
+# "data": { "device": "ide1-cd0",
476
+# "id": "ide0-1-0",
477
+# "tray-open": true } }
478
+#
479
+# <- { "return": {} }
480
+#
481
+##
482
+{ 'command': 'blockdev-open-tray',
483
+ 'data': { '*device': 'str',
484
+ '*id': 'str',
485
+ '*force': 'bool' } }
486
+
487
+##
488
+# @blockdev-close-tray:
489
+#
490
+# Closes a block device's tray. If there is a block driver state tree associated
491
+# with the block device (which is currently ejected), that tree will be loaded
492
+# as the medium.
493
+#
494
+# If the tray was already closed before, this will be a no-op.
495
+#
496
+# @device: Block device name (deprecated, use @id instead)
497
+#
498
+# @id: The name or QOM path of the guest device (since: 2.8)
499
+#
500
+# Since: 2.5
501
+#
502
+# Example:
503
+#
504
+# -> { "execute": "blockdev-close-tray",
505
+# "arguments": { "id": "ide0-1-0" } }
506
+#
507
+# <- { "timestamp": { "seconds": 1418751345,
508
+# "microseconds": 272147 },
509
+# "event": "DEVICE_TRAY_MOVED",
510
+# "data": { "device": "ide1-cd0",
511
+# "id": "ide0-1-0",
512
+# "tray-open": false } }
513
+#
514
+# <- { "return": {} }
515
+#
516
+##
517
+{ 'command': 'blockdev-close-tray',
518
+ 'data': { '*device': 'str',
519
+ '*id': 'str' } }
520
+
521
+##
522
+# @blockdev-remove-medium:
523
+#
524
+# Removes a medium (a block driver state tree) from a block device. That block
525
+# device's tray must currently be open (unless there is no attached guest
526
+# device).
527
+#
528
+# If the tray is open and there is no medium inserted, this will be a no-op.
529
+#
530
+# @id: The name or QOM path of the guest device
531
+#
532
+# Since: 2.12
533
+#
534
+# Example:
535
+#
536
+# -> { "execute": "blockdev-remove-medium",
537
+# "arguments": { "id": "ide0-1-0" } }
538
+#
539
+# <- { "error": { "class": "GenericError",
540
+# "desc": "Tray of device 'ide0-1-0' is not open" } }
541
+#
542
+# -> { "execute": "blockdev-open-tray",
543
+# "arguments": { "id": "ide0-1-0" } }
544
+#
545
+# <- { "timestamp": { "seconds": 1418751627,
546
+# "microseconds": 549958 },
547
+# "event": "DEVICE_TRAY_MOVED",
548
+# "data": { "device": "ide1-cd0",
549
+# "id": "ide0-1-0",
550
+# "tray-open": true } }
551
+#
552
+# <- { "return": {} }
553
+#
554
+# -> { "execute": "blockdev-remove-medium",
555
+# "arguments": { "id": "ide0-1-0" } }
556
+#
557
+# <- { "return": {} }
558
+#
559
+##
560
+{ 'command': 'blockdev-remove-medium',
561
+ 'data': { 'id': 'str' } }
562
+
563
+##
564
+# @blockdev-insert-medium:
565
+#
566
+# Inserts a medium (a block driver state tree) into a block device. That block
567
+# device's tray must currently be open (unless there is no attached guest
568
+# device) and there must be no medium inserted already.
569
+#
570
+# @id: The name or QOM path of the guest device
571
+#
572
+# @node-name: name of a node in the block driver state graph
573
+#
574
+# Since: 2.12
575
+#
576
+# Example:
577
+#
578
+# -> { "execute": "blockdev-add",
579
+# "arguments": {
580
+# "node-name": "node0",
581
+# "driver": "raw",
582
+# "file": { "driver": "file",
583
+# "filename": "fedora.iso" } } }
584
+# <- { "return": {} }
585
+#
586
+# -> { "execute": "blockdev-insert-medium",
587
+# "arguments": { "id": "ide0-1-0",
588
+# "node-name": "node0" } }
589
+#
590
+# <- { "return": {} }
591
+#
592
+##
593
+{ 'command': 'blockdev-insert-medium',
594
+ 'data': { 'id': 'str',
595
+ 'node-name': 'str'} }
596
+
597
+
598
+##
599
+# @BlockdevChangeReadOnlyMode:
600
+#
601
+# Specifies the new read-only mode of a block device subject to the
602
+# @blockdev-change-medium command.
603
+#
604
+# @retain: Retains the current read-only mode
605
+#
606
+# @read-only: Makes the device read-only
607
+#
608
+# @read-write: Makes the device writable
609
+#
610
+# Since: 2.3
611
+#
612
+##
613
+{ 'enum': 'BlockdevChangeReadOnlyMode',
614
+ 'data': ['retain', 'read-only', 'read-write'] }
615
+
616
+
617
+##
618
+# @blockdev-change-medium:
619
+#
620
+# Changes the medium inserted into a block device by ejecting the current medium
621
+# and loading a new image file which is inserted as the new medium (this command
622
+# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
623
+# and blockdev-close-tray).
624
+#
625
+# @device: Block device name (deprecated, use @id instead)
626
+#
627
+# @id: The name or QOM path of the guest device
628
+# (since: 2.8)
629
+#
630
+# @filename: filename of the new image to be loaded
631
+#
632
+# @format: format to open the new image with (defaults to
633
+# the probed format)
634
+#
635
+# @read-only-mode: change the read-only mode of the device; defaults
636
+# to 'retain'
637
+#
638
+# Since: 2.5
639
+#
640
+# Examples:
641
+#
642
+# 1. Change a removable medium
643
+#
644
+# -> { "execute": "blockdev-change-medium",
645
+# "arguments": { "id": "ide0-1-0",
646
+# "filename": "/srv/images/Fedora-12-x86_64-DVD.iso",
647
+# "format": "raw" } }
648
+# <- { "return": {} }
649
+#
650
+# 2. Load a read-only medium into a writable drive
651
+#
652
+# -> { "execute": "blockdev-change-medium",
653
+# "arguments": { "id": "floppyA",
654
+# "filename": "/srv/images/ro.img",
655
+# "format": "raw",
656
+# "read-only-mode": "retain" } }
657
+#
658
+# <- { "error":
659
+# { "class": "GenericError",
660
+# "desc": "Could not open '/srv/images/ro.img': Permission denied" } }
661
+#
662
+# -> { "execute": "blockdev-change-medium",
663
+# "arguments": { "id": "floppyA",
664
+# "filename": "/srv/images/ro.img",
665
+# "format": "raw",
666
+# "read-only-mode": "read-only" } }
667
+#
668
+# <- { "return": {} }
669
+#
670
+##
671
+{ 'command': 'blockdev-change-medium',
672
+ 'data': { '*device': 'str',
673
+ '*id': 'str',
674
+ 'filename': 'str',
675
+ '*format': 'str',
676
+ '*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
677
+
678
+
679
##
680
# @DEVICE_TRAY_MOVED:
681
#
682
@@ -XXX,XX +XXX,XX @@
683
##
684
{ 'event': 'PR_MANAGER_STATUS_CHANGED',
685
'data': { 'id': 'str', 'connected': 'bool' } }
686
+
687
+##
688
+# @block_set_io_throttle:
689
+#
690
+# Change I/O throttle limits for a block drive.
691
+#
692
+# Since QEMU 2.4, each device with I/O limits is member of a throttle
693
+# group.
694
+#
695
+# If two or more devices are members of the same group, the limits
696
+# will apply to the combined I/O of the whole group in a round-robin
697
+# fashion. Therefore, setting new I/O limits to a device will affect
698
+# the whole group.
699
+#
700
+# The name of the group can be specified using the 'group' parameter.
701
+# If the parameter is unset, it is assumed to be the current group of
702
+# that device. If it's not in any group yet, the name of the device
703
+# will be used as the name for its group.
704
+#
705
+# The 'group' parameter can also be used to move a device to a
706
+# different group. In this case the limits specified in the parameters
707
+# will be applied to the new group only.
708
+#
709
+# I/O limits can be disabled by setting all of them to 0. In this case
710
+# the device will be removed from its group and the rest of its
711
+# members will not be affected. The 'group' parameter is ignored.
712
+#
713
+# Returns: - Nothing on success
714
+# - If @device is not a valid block device, DeviceNotFound
715
+#
716
+# Since: 1.1
717
+#
718
+# Example:
719
+#
720
+# -> { "execute": "block_set_io_throttle",
721
+# "arguments": { "id": "virtio-blk-pci0/virtio-backend",
722
+# "bps": 0,
723
+# "bps_rd": 0,
724
+# "bps_wr": 0,
725
+# "iops": 512,
726
+# "iops_rd": 0,
727
+# "iops_wr": 0,
728
+# "bps_max": 0,
729
+# "bps_rd_max": 0,
730
+# "bps_wr_max": 0,
731
+# "iops_max": 0,
732
+# "iops_rd_max": 0,
733
+# "iops_wr_max": 0,
734
+# "bps_max_length": 0,
735
+# "iops_size": 0 } }
736
+# <- { "return": {} }
737
+#
738
+# -> { "execute": "block_set_io_throttle",
739
+# "arguments": { "id": "ide0-1-0",
740
+# "bps": 1000000,
741
+# "bps_rd": 0,
742
+# "bps_wr": 0,
743
+# "iops": 0,
744
+# "iops_rd": 0,
745
+# "iops_wr": 0,
746
+# "bps_max": 8000000,
747
+# "bps_rd_max": 0,
748
+# "bps_wr_max": 0,
749
+# "iops_max": 0,
750
+# "iops_rd_max": 0,
751
+# "iops_wr_max": 0,
752
+# "bps_max_length": 60,
753
+# "iops_size": 0 } }
754
+# <- { "return": {} }
755
+##
756
+{ 'command': 'block_set_io_throttle', 'boxed': true,
757
+ 'data': 'BlockIOThrottle' }
758
+
759
+##
760
+# @block-latency-histogram-set:
761
+#
762
+# Manage read, write and flush latency histograms for the device.
763
+#
764
+# If only @id parameter is specified, remove all present latency histograms
765
+# for the device. Otherwise, add/reset some of (or all) latency histograms.
766
+#
767
+# @id: The name or QOM path of the guest device.
768
+#
769
+# @boundaries: list of interval boundary values (see description in
770
+# BlockLatencyHistogramInfo definition). If specified, all
771
+# latency histograms are removed, and empty ones created for all
772
+# io types with intervals corresponding to @boundaries (except for
773
+# io types, for which specific boundaries are set through the
774
+# following parameters).
775
+#
776
+# @boundaries-read: list of interval boundary values for read latency
777
+# histogram. If specified, old read latency histogram is
778
+# removed, and empty one created with intervals
779
+# corresponding to @boundaries-read. The parameter has higher
780
+# priority then @boundaries.
781
+#
782
+# @boundaries-write: list of interval boundary values for write latency
783
+# histogram.
784
+#
785
+# @boundaries-flush: list of interval boundary values for flush latency
786
+# histogram.
787
+#
788
+# Returns: error if device is not found or any boundary arrays are invalid.
789
+#
790
+# Since: 4.0
791
+#
792
+# Example: set new histograms for all io types with intervals
793
+# [0, 10), [10, 50), [50, 100), [100, +inf):
794
+#
795
+# -> { "execute": "block-latency-histogram-set",
796
+# "arguments": { "id": "drive0",
797
+# "boundaries": [10, 50, 100] } }
798
+# <- { "return": {} }
799
+#
800
+# Example: set new histogram only for write, other histograms will remain
801
+# not changed (or not created):
802
+#
803
+# -> { "execute": "block-latency-histogram-set",
804
+# "arguments": { "id": "drive0",
805
+# "boundaries-write": [10, 50, 100] } }
806
+# <- { "return": {} }
807
+#
808
+# Example: set new histograms with the following intervals:
809
+# read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
810
+# write: [0, 1000), [1000, 5000), [5000, +inf)
811
+#
812
+# -> { "execute": "block-latency-histogram-set",
813
+# "arguments": { "id": "drive0",
814
+# "boundaries": [10, 50, 100],
815
+# "boundaries-write": [1000, 5000] } }
816
+# <- { "return": {} }
817
+#
818
+# Example: remove all latency histograms:
819
+#
820
+# -> { "execute": "block-latency-histogram-set",
821
+# "arguments": { "id": "drive0" } }
822
+# <- { "return": {} }
823
+##
824
+{ 'command': 'block-latency-histogram-set',
825
+ 'data': {'id': 'str',
826
+ '*boundaries': ['uint64'],
827
+ '*boundaries-read': ['uint64'],
828
+ '*boundaries-write': ['uint64'],
829
+ '*boundaries-flush': ['uint64'] } }
830
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
831
index XXXXXXX..XXXXXXX 100644
832
--- a/monitor/qmp-cmds.c
833
+++ b/monitor/qmp-cmds.c
834
@@ -XXX,XX +XXX,XX @@
835
#include "sysemu/blockdev.h"
836
#include "sysemu/block-backend.h"
837
#include "qapi/error.h"
838
-#include "qapi/qapi-commands-block-core.h"
839
+#include "qapi/qapi-commands-block.h"
840
#include "qapi/qapi-commands-control.h"
841
#include "qapi/qapi-commands-machine.h"
842
#include "qapi/qapi-commands-misc.h"
40
--
843
--
41
2.13.6
844
2.20.1
42
845
43
846
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a --blockdev option to the storage daemon that works the same
2
as the -blockdev option of the system emulator.
2
3
3
We can easily repair unaligned preallocated zero clusters by discarding
4
In order to be able to link with blockdev.o, we also need to change
4
them, so why not do it?
5
stream.o from common-obj to block-obj, which is where all other block
6
jobs already are.
5
7
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
In contrast to the system emulator, qemu-storage-daemon options will be
7
Message-id: 20171110203759.14018-2-mreitz@redhat.com
9
processed in the order they are given. The user needs to take care to
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
refer to other objects only after defining them.
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20200224143008.13362-7-kwolf@redhat.com>
14
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
16
---
11
block/qcow2-refcount.c | 70 ++++++++++++++++++++++++++++++++++++++--------
17
qemu-storage-daemon.c | 31 +++++++++++++++++++++++++++++++
12
tests/qemu-iotests/060 | 3 +-
18
Makefile | 5 ++++-
13
tests/qemu-iotests/060.out | 9 ++++++
19
Makefile.objs | 7 +++++++
14
3 files changed, 69 insertions(+), 13 deletions(-)
20
block/Makefile.objs | 2 +-
21
4 files changed, 43 insertions(+), 2 deletions(-)
15
22
16
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
23
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2-refcount.c
25
--- a/qemu-storage-daemon.c
19
+++ b/block/qcow2-refcount.c
26
+++ b/qemu-storage-daemon.c
20
@@ -XXX,XX +XXX,XX @@ enum {
27
@@ -XXX,XX +XXX,XX @@
21
static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
28
#include "crypto/init.h"
22
void **refcount_table,
29
23
int64_t *refcount_table_size, int64_t l2_offset,
30
#include "qapi/error.h"
24
- int flags)
31
+#include "qapi/qapi-visit-block-core.h"
25
+ int flags, BdrvCheckMode fix)
32
+#include "qapi/qapi-commands-block-core.h"
33
+#include "qapi/qobject-input-visitor.h"
34
+
35
#include "qemu-common.h"
36
#include "qemu-version.h"
37
#include "qemu/config-file.h"
38
@@ -XXX,XX +XXX,XX @@ static void help(void)
39
" specify tracing options\n"
40
" -V, --version output version information and exit\n"
41
"\n"
42
+" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
43
+" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
44
+" [,read-only=on|off][,auto-read-only=on|off]\n"
45
+" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
46
+" [,driver specific parameters...]\n"
47
+" configure a block backend\n"
48
+"\n"
49
QEMU_HELP_BOTTOM "\n",
50
error_get_progname());
51
}
52
53
+enum {
54
+ OPTION_BLOCKDEV = 256,
55
+};
56
+
57
static void process_options(int argc, char *argv[])
26
{
58
{
27
BDRVQcow2State *s = bs->opaque;
59
int c;
28
uint64_t *l2_table, l2_entry;
60
29
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
61
static const struct option long_options[] = {
30
next_contiguous_offset = offset + s->cluster_size;
62
+ {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
31
}
63
{"help", no_argument, NULL, 'h'},
32
64
{"trace", required_argument, NULL, 'T'},
33
+ /* Correct offsets are cluster aligned */
65
{"version", no_argument, NULL, 'V'},
34
+ if (offset_into_cluster(s, offset)) {
66
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
35
+ if (qcow2_get_cluster_type(l2_entry) ==
67
printf("qemu-storage-daemon version "
36
+ QCOW2_CLUSTER_ZERO_ALLOC)
68
QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
37
+ {
69
exit(EXIT_SUCCESS);
38
+ fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero "
70
+ case OPTION_BLOCKDEV:
39
+ "cluster is not properly aligned; L2 entry "
71
+ {
40
+ "corrupted.\n",
72
+ Visitor *v;
41
+ fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
73
+ BlockdevOptions *options;
42
+ offset);
43
+ if (fix & BDRV_FIX_ERRORS) {
44
+ uint64_t l2e_offset =
45
+ l2_offset + (uint64_t)i * sizeof(uint64_t);
46
+
74
+
47
+ l2_entry = QCOW_OFLAG_ZERO;
75
+ v = qobject_input_visitor_new_str(optarg, "driver",
48
+ l2_table[i] = cpu_to_be64(l2_entry);
76
+ &error_fatal);
49
+ ret = qcow2_pre_write_overlap_check(bs,
50
+ QCOW2_OL_ACTIVE_L2 | QCOW2_OL_INACTIVE_L2,
51
+ l2e_offset, sizeof(uint64_t));
52
+ if (ret < 0) {
53
+ fprintf(stderr, "ERROR: Overlap check failed\n");
54
+ res->check_errors++;
55
+ /* Something is seriously wrong, so abort checking
56
+ * this L2 table */
57
+ goto fail;
58
+ }
59
+
77
+
60
+ ret = bdrv_pwrite_sync(bs->file, l2e_offset,
78
+ visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
61
+ &l2_table[i], sizeof(uint64_t));
79
+ visit_free(v);
62
+ if (ret < 0) {
80
+
63
+ fprintf(stderr, "ERROR: Failed to overwrite L2 "
81
+ qmp_blockdev_add(options, &error_fatal);
64
+ "table entry: %s\n", strerror(-ret));
82
+ qapi_free_BlockdevOptions(options);
65
+ res->check_errors++;
83
+ break;
66
+ /* Do not abort, continue checking the rest of this
67
+ * L2 table's entries */
68
+ } else {
69
+ res->corruptions_fixed++;
70
+ /* Skip marking the cluster as used
71
+ * (it is unused now) */
72
+ continue;
73
+ }
74
+ } else {
75
+ res->corruptions++;
76
+ }
77
+ } else {
78
+ fprintf(stderr, "ERROR offset=%" PRIx64 ": Data cluster is "
79
+ "not properly aligned; L2 entry corrupted.\n", offset);
80
+ res->corruptions++;
81
+ }
82
+ }
84
+ }
85
default:
86
g_assert_not_reached();
87
}
88
diff --git a/Makefile b/Makefile
89
index XXXXXXX..XXXXXXX 100644
90
--- a/Makefile
91
+++ b/Makefile
92
@@ -XXX,XX +XXX,XX @@ dummy := $(call unnest-vars,, \
93
qga-vss-dll-obj-y \
94
block-obj-y \
95
block-obj-m \
96
+ storage-daemon-obj-y \
97
+ storage-daemon-obj-m \
98
crypto-obj-y \
99
qom-obj-y \
100
io-obj-y \
101
@@ -XXX,XX +XXX,XX @@ TARGET_DIRS_RULES := $(foreach t, all fuzz clean install, $(addsuffix /$(t), $(T
102
SOFTMMU_ALL_RULES=$(filter %-softmmu/all, $(TARGET_DIRS_RULES))
103
$(SOFTMMU_ALL_RULES): $(authz-obj-y)
104
$(SOFTMMU_ALL_RULES): $(block-obj-y)
105
+$(SOFTMMU_ALL_RULES): $(storage-daemon-obj-y)
106
$(SOFTMMU_ALL_RULES): $(chardev-obj-y)
107
$(SOFTMMU_ALL_RULES): $(crypto-obj-y)
108
$(SOFTMMU_ALL_RULES): $(io-obj-y)
109
@@ -XXX,XX +XXX,XX @@ qemu-img.o: qemu-img-cmds.h
110
qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
111
qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
112
qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
113
-qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
114
+qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS)
115
116
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
117
118
diff --git a/Makefile.objs b/Makefile.objs
119
index XXXXXXX..XXXXXXX 100644
120
--- a/Makefile.objs
121
+++ b/Makefile.objs
122
@@ -XXX,XX +XXX,XX @@ io-obj-y = io/
123
124
endif # CONFIG_SOFTMMU or CONFIG_TOOLS
125
126
+#######################################################################
127
+# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are
128
+# used for system emulation, too, but specified separately there)
83
+
129
+
84
/* Mark cluster as used */
130
+storage-daemon-obj-y = block/
85
ret = qcow2_inc_refcounts_imrt(bs, res,
131
+storage-daemon-obj-y += blockdev.o iothread.o
86
refcount_table, refcount_table_size,
132
+
87
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
133
######################################################################
88
if (ret < 0) {
134
# Target independent part of system emulation. The long term path is to
89
goto fail;
135
# suppress *all* target specific code in case of system emulation, i.e. a
90
}
136
diff --git a/block/Makefile.objs b/block/Makefile.objs
91
-
92
- /* Correct offsets are cluster aligned */
93
- if (offset_into_cluster(s, offset)) {
94
- fprintf(stderr, "ERROR offset=%" PRIx64 ": Cluster is not "
95
- "properly aligned; L2 entry corrupted.\n", offset);
96
- res->corruptions++;
97
- }
98
break;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
102
void **refcount_table,
103
int64_t *refcount_table_size,
104
int64_t l1_table_offset, int l1_size,
105
- int flags)
106
+ int flags, BdrvCheckMode fix)
107
{
108
BDRVQcow2State *s = bs->opaque;
109
uint64_t *l1_table = NULL, l2_offset, l1_size2;
110
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
111
112
/* Process and check L2 entries */
113
ret = check_refcounts_l2(bs, res, refcount_table,
114
- refcount_table_size, l2_offset, flags);
115
+ refcount_table_size, l2_offset, flags,
116
+ fix);
117
if (ret < 0) {
118
goto fail;
119
}
120
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
121
122
/* current L1 table */
123
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
124
- s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO);
125
+ s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO,
126
+ fix);
127
if (ret < 0) {
128
return ret;
129
}
130
@@ -XXX,XX +XXX,XX @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
131
for (i = 0; i < s->nb_snapshots; i++) {
132
sn = s->snapshots + i;
133
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
134
- sn->l1_table_offset, sn->l1_size, 0);
135
+ sn->l1_table_offset, sn->l1_size, 0, fix);
136
if (ret < 0) {
137
return ret;
138
}
139
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
140
index XXXXXXX..XXXXXXX 100755
141
--- a/tests/qemu-iotests/060
142
+++ b/tests/qemu-iotests/060
143
@@ -XXX,XX +XXX,XX @@ poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x00\x2a\x01"
144
# Let's write to it!
145
$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
146
147
-# Can't repair this yet (TODO: We can just deallocate the cluster)
148
+echo '--- Repairing ---'
149
+_check_test_img -r all
150
151
echo
152
echo '=== Discarding with an unaligned refblock ==='
153
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
154
index XXXXXXX..XXXXXXX 100644
137
index XXXXXXX..XXXXXXX 100644
155
--- a/tests/qemu-iotests/060.out
138
--- a/block/Makefile.objs
156
+++ b/tests/qemu-iotests/060.out
139
+++ b/block/Makefile.objs
157
@@ -XXX,XX +XXX,XX @@ discard 65536/65536 bytes at offset 0
140
@@ -XXX,XX +XXX,XX @@ block-obj-y += aio_task.o
158
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
141
block-obj-y += backup-top.o
159
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
142
block-obj-y += filter-compress.o
160
write failed: Input/output error
143
161
+--- Repairing ---
144
-common-obj-y += stream.o
162
+Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted.
145
+block-obj-y += stream.o
163
+The following inconsistencies were found and repaired:
146
164
+
147
common-obj-y += qapi-sysemu.o
165
+ 0 leaked clusters
166
+ 1 corruptions
167
+
168
+Double checking the fixed image now...
169
+No errors were found on the image.
170
171
=== Discarding with an unaligned refblock ===
172
148
173
--
149
--
174
2.13.6
150
2.20.1
175
151
176
152
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Mapping object-add to the command line as is doesn't result in nice
2
2
syntax because of the nesting introduced with 'props'. This becomes
3
_filter_img_info should remove format-specific information, too. We
3
nicer and more consistent with device_add and netdev_add when we accept
4
already have such a filter in _img_info, and it is very useful for
4
properties for the object on the top level instead.
5
query-block-named-block-nodes (etc.), too.
5
6
6
'props' is still accepted after this patch, but marked as deprecated.
7
However, in 198 we need that information (but we still want the rest of
7
8
the filter), so make that filtering optional. Note that "the rest of
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
the filter" includes filtering of the test directory, so we can drop the
9
Message-Id: <20200224143008.13362-8-kwolf@redhat.com>
10
_filter_testdir from 198 at the same time.
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-id: 20171123020832.8165-7-mreitz@redhat.com
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Fam Zheng <famz@redhat.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
12
---
18
tests/qemu-iotests/198 | 6 ++++--
13
qapi/qom.json | 12 +++++++---
19
tests/qemu-iotests/common.filter | 29 ++++++++++++++++++++++++++++-
14
docs/system/deprecated.rst | 5 ++++
20
2 files changed, 32 insertions(+), 3 deletions(-)
15
include/qom/object_interfaces.h | 7 ++++++
21
16
hw/block/xen-block.c | 11 ++++++++-
22
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
17
monitor/misc.c | 2 ++
23
index XXXXXXX..XXXXXXX 100755
18
qom/qom-qmp-cmds.c | 42 +++++++++++++++++++++++++++------
24
--- a/tests/qemu-iotests/198
19
6 files changed, 68 insertions(+), 11 deletions(-)
25
+++ b/tests/qemu-iotests/198
20
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO --object $SECRET0 --object $SECRET1 -c "read -P 0x9 0 $size" --image-op
21
diff --git a/qapi/qom.json b/qapi/qom.json
27
22
index XXXXXXX..XXXXXXX 100644
28
echo
23
--- a/qapi/qom.json
29
echo "== checking image base =="
24
+++ b/qapi/qom.json
30
-$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info | _filter_testdir | sed -e "/^disk size:/ D"
25
@@ -XXX,XX +XXX,XX @@
31
+$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
26
#
32
+ | sed -e "/^disk size:/ D"
27
# @id: the name of the new object
33
28
#
34
echo
29
-# @props: a dictionary of properties to be passed to the backend
35
echo "== checking image layer =="
30
+# @props: a dictionary of properties to be passed to the backend. Deprecated
36
-$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info | _filter_testdir | sed -e "/^disk size:/ D"
31
+# since 5.0, specify the properties on the top level instead. It is an
37
+$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
32
+# error to specify the same option both on the top level and in @props.
38
+ | sed -e "/^disk size:/ D"
33
+#
39
34
+# Additional arguments depend on qom-type and are passed to the backend
40
35
+# unchanged.
41
# success, all done
36
#
42
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
37
# Returns: Nothing on success
43
index XXXXXXX..XXXXXXX 100644
38
# Error if @qom-type is not a valid class name
44
--- a/tests/qemu-iotests/common.filter
39
@@ -XXX,XX +XXX,XX @@
45
+++ b/tests/qemu-iotests/common.filter
40
#
46
@@ -XXX,XX +XXX,XX @@ _filter_img_create()
41
# -> { "execute": "object-add",
47
42
# "arguments": { "qom-type": "rng-random", "id": "rng1",
48
_filter_img_info()
43
-# "props": { "filename": "/dev/hwrng" } } }
44
+# "filename": "/dev/hwrng" } }
45
# <- { "return": {} }
46
#
47
##
48
{ 'command': 'object-add',
49
- 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'} }
50
+ 'data': {'qom-type': 'str', 'id': 'str', '*props': 'any'},
51
+ 'gen': false } # so we can get the additional arguments
52
53
##
54
# @object-del:
55
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
56
index XXXXXXX..XXXXXXX 100644
57
--- a/docs/system/deprecated.rst
58
+++ b/docs/system/deprecated.rst
59
@@ -XXX,XX +XXX,XX @@ Use ``migrate-set-parameters`` instead.
60
61
Use ``migrate-set-parameters`` and ``query-migrate-parameters`` instead.
62
63
+``object-add`` option ``props`` (since 5.0)
64
+'''''''''''''''''''''''''''''''''''''''''''
65
+
66
+Specify the properties for the object as top-level arguments instead.
67
+
68
``query-block`` result field ``dirty-bitmaps[i].status`` (since 4.0)
69
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
70
71
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/qom/object_interfaces.h
74
+++ b/include/qom/object_interfaces.h
75
@@ -XXX,XX +XXX,XX @@ void user_creatable_del(const char *id, Error **errp);
76
*/
77
void user_creatable_cleanup(void);
78
79
+/**
80
+ * qmp_object_add:
81
+ *
82
+ * QMP command handler for object-add. See the QAPI schema for documentation.
83
+ */
84
+void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp);
85
+
86
#endif
87
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/block/xen-block.c
90
+++ b/hw/block/xen-block.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/visitor.h"
93
#include "qapi/qmp/qdict.h"
94
#include "qapi/qmp/qstring.h"
95
+#include "qom/object_interfaces.h"
96
#include "hw/xen/xen_common.h"
97
#include "hw/block/xen_blkif.h"
98
#include "hw/qdev-properties.h"
99
@@ -XXX,XX +XXX,XX @@ static XenBlockIOThread *xen_block_iothread_create(const char *id,
49
{
100
{
50
+ if [[ "$1" == "--format-specific" ]]; then
101
XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1);
51
+ local format_specific=1
102
Error *local_err = NULL;
52
+ shift
103
+ QDict *opts;
53
+ else
104
+ QObject *ret_data;
54
+ local format_specific=0
105
55
+ fi
106
iothread->id = g_strdup(id);
56
+
107
57
+ discard=0
108
- qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err);
58
+ regex_json_spec_start='^ *"format-specific": \{'
109
+ opts = qdict_new();
59
sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
110
+ qdict_put_str(opts, "qom-type", TYPE_IOTHREAD);
60
-e "s#$TEST_DIR#TEST_DIR#g" \
111
+ qdict_put_str(opts, "id", id);
61
-e "s#$IMGFMT#IMGFMT#g" \
112
+ qmp_object_add(opts, &ret_data, &local_err);
62
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
113
+ qobject_unref(opts);
63
-e "/block_state_zero: \\(on\\|off\\)/d" \
114
+ qobject_unref(ret_data);
64
-e "/log_size: [0-9]\\+/d" \
115
+
65
-e "s/iters: [0-9]\\+/iters: 1024/" \
116
if (local_err) {
66
- -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/"
117
error_propagate(errp, local_err);
67
+ -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \
118
68
+ while IFS='' read -r line; do
119
diff --git a/monitor/misc.c b/monitor/misc.c
69
+ if [[ $format_specific == 1 ]]; then
120
index XXXXXXX..XXXXXXX 100644
70
+ discard=0
121
--- a/monitor/misc.c
71
+ elif [[ $line == "Format specific information:" ]]; then
122
+++ b/monitor/misc.c
72
+ discard=1
123
@@ -XXX,XX +XXX,XX @@ static void monitor_init_qmp_commands(void)
73
+ elif [[ $line =~ $regex_json_spec_start ]]; then
124
QCO_NO_OPTIONS);
74
+ discard=2
125
qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
75
+ regex_json_spec_end="^${line%%[^ ]*}\\},? *$"
126
QCO_NO_OPTIONS);
76
+ fi
127
+ qmp_register_command(&qmp_commands, "object-add", qmp_object_add,
77
+ if [[ $discard == 0 ]]; then
128
+ QCO_NO_OPTIONS);
78
+ echo "$line"
129
79
+ elif [[ $discard == 1 && ! $line ]]; then
130
QTAILQ_INIT(&qmp_cap_negotiation_commands);
80
+ echo
131
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
81
+ discard=0
132
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
82
+ elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then
133
index XXXXXXX..XXXXXXX 100644
83
+ discard=0
134
--- a/qom/qom-qmp-cmds.c
84
+ fi
135
+++ b/qom/qom-qmp-cmds.c
85
+ done
136
@@ -XXX,XX +XXX,XX @@
137
*/
138
139
#include "qemu/osdep.h"
140
+#include "block/qdict.h"
141
#include "hw/qdev-core.h"
142
#include "qapi/error.h"
143
#include "qapi/qapi-commands-qdev.h"
144
@@ -XXX,XX +XXX,XX @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
145
return prop_list;
86
}
146
}
87
147
88
# filter out offsets and file names from qemu-img map; good for both
148
-void qmp_object_add(const char *type, const char *id,
149
- bool has_props, QObject *props, Error **errp)
150
+void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
151
{
152
+ QObject *props;
153
QDict *pdict;
154
Visitor *v;
155
Object *obj;
156
+ const char *type;
157
+ const char *id;
158
159
+ type = qdict_get_try_str(qdict, "qom-type");
160
+ if (!type) {
161
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
162
+ return;
163
+ } else {
164
+ type = g_strdup(type);
165
+ qdict_del(qdict, "qom-type");
166
+ }
167
+
168
+ id = qdict_get_try_str(qdict, "id");
169
+ if (!id) {
170
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
171
+ return;
172
+ } else {
173
+ id = g_strdup(id);
174
+ qdict_del(qdict, "id");
175
+ }
176
+
177
+ props = qdict_get(qdict, "props");
178
if (props) {
179
pdict = qobject_to(QDict, props);
180
if (!pdict) {
181
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(const char *type, const char *id,
182
return;
183
}
184
qobject_ref(pdict);
185
- } else {
186
- pdict = qdict_new();
187
+ qdict_del(qdict, "props");
188
+ qdict_join(qdict, pdict, false);
189
+ if (qdict_size(pdict) != 0) {
190
+ error_setg(errp, "Option in 'props' conflicts with top level");
191
+ qobject_unref(pdict);
192
+ return;
193
+ }
194
+ qobject_unref(pdict);
195
}
196
197
- v = qobject_input_visitor_new(QOBJECT(pdict));
198
- obj = user_creatable_add_type(type, id, pdict, v, errp);
199
+ v = qobject_input_visitor_new(QOBJECT(qdict));
200
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
201
visit_free(v);
202
if (obj) {
203
object_unref(obj);
204
}
205
- qobject_unref(pdict);
206
+ *ret_data = QOBJECT(qdict_new());
207
}
208
209
void qmp_object_del(const char *id, Error **errp)
89
--
210
--
90
2.13.6
211
2.20.1
91
212
92
213
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Add a command line option to create user-creatable QOM objects.
2
2
3
067 works very well with compat=0.10 once you remove format-specific
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
information from the QMP output.
4
Message-Id: <20200224143008.13362-9-kwolf@redhat.com>
5
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
qemu-storage-daemon.c | 47 +++++++++++++++++++++++++++++++++++++++++++
9
Makefile.objs | 2 +-
10
qom/Makefile.objs | 1 +
11
3 files changed, 49 insertions(+), 1 deletion(-)
5
12
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
7
Message-id: 20171123020832.8165-14-mreitz@redhat.com
14
index XXXXXXX..XXXXXXX 100644
8
Reviewed-by: John Snow <jsnow@redhat.com>
15
--- a/qemu-storage-daemon.c
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
+++ b/qemu-storage-daemon.c
10
---
17
@@ -XXX,XX +XXX,XX @@
11
tests/qemu-iotests/067 | 3 +-
18
#include "qapi/error.h"
12
tests/qemu-iotests/067.out | 97 +++++++++++++---------------------------------
19
#include "qapi/qapi-visit-block-core.h"
13
2 files changed, 28 insertions(+), 72 deletions(-)
20
#include "qapi/qapi-commands-block-core.h"
14
21
+#include "qapi/qmp/qdict.h"
15
diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067
22
#include "qapi/qobject-input-visitor.h"
16
index XXXXXXX..XXXXXXX 100755
23
17
--- a/tests/qemu-iotests/067
24
#include "qemu-common.h"
18
+++ b/tests/qemu-iotests/067
25
#include "qemu-version.h"
19
@@ -XXX,XX +XXX,XX @@ function run_qemu()
26
#include "qemu/config-file.h"
20
{
27
#include "qemu/error-report.h"
21
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \
28
+#include "qemu/help_option.h"
22
| _filter_actual_image_size \
29
#include "qemu/log.h"
23
- | _filter_generated_node_ids | _filter_qmp_events
30
#include "qemu/main-loop.h"
24
+ | _filter_generated_node_ids | _filter_qmp_events \
31
#include "qemu/module.h"
25
+ | _filter_img_info
32
+#include "qemu/option.h"
33
+#include "qom/object_interfaces.h"
34
35
#include "trace/control.h"
36
37
@@ -XXX,XX +XXX,XX @@ static void help(void)
38
" [,driver specific parameters...]\n"
39
" configure a block backend\n"
40
"\n"
41
+" --object help list object types that can be added\n"
42
+" --object <type>,help list properties for the given object type\n"
43
+" --object <type>[,<property>=<value>...]\n"
44
+" create a new object of type <type>, setting\n"
45
+" properties in the order they are specified. Note\n"
46
+" that the 'id' property must be set.\n"
47
+" See the qemu(1) man page for documentation of the\n"
48
+" objects that can be added.\n"
49
+"\n"
50
QEMU_HELP_BOTTOM "\n",
51
error_get_progname());
26
}
52
}
27
53
28
size=128M
54
enum {
29
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
55
OPTION_BLOCKDEV = 256,
56
+ OPTION_OBJECT,
57
+};
58
+
59
+static QemuOptsList qemu_object_opts = {
60
+ .name = "object",
61
+ .implied_opt_name = "qom-type",
62
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
63
+ .desc = {
64
+ { }
65
+ },
66
};
67
68
static void process_options(int argc, char *argv[])
69
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
70
static const struct option long_options[] = {
71
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
72
{"help", no_argument, NULL, 'h'},
73
+ {"object", required_argument, NULL, OPTION_OBJECT},
74
{"trace", required_argument, NULL, 'T'},
75
{"version", no_argument, NULL, 'V'},
76
{0, 0, 0, 0}
77
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
78
qapi_free_BlockdevOptions(options);
79
break;
80
}
81
+ case OPTION_OBJECT:
82
+ {
83
+ QemuOpts *opts;
84
+ const char *type;
85
+ QDict *args;
86
+ QObject *ret_data = NULL;
87
+
88
+ /* FIXME The keyval parser rejects 'help' arguments, so we must
89
+ * unconditionall try QemuOpts first. */
90
+ opts = qemu_opts_parse(&qemu_object_opts,
91
+ optarg, true, &error_fatal);
92
+ type = qemu_opt_get(opts, "qom-type");
93
+ if (type && user_creatable_print_help(type, opts)) {
94
+ exit(EXIT_SUCCESS);
95
+ }
96
+ qemu_opts_del(opts);
97
+
98
+ args = keyval_parse(optarg, "qom-type", &error_fatal);
99
+ qmp_object_add(args, &ret_data, &error_fatal);
100
+ qobject_unref(args);
101
+ qobject_unref(ret_data);
102
+ break;
103
+ }
104
default:
105
g_assert_not_reached();
106
}
107
diff --git a/Makefile.objs b/Makefile.objs
30
index XXXXXXX..XXXXXXX 100644
108
index XXXXXXX..XXXXXXX 100644
31
--- a/tests/qemu-iotests/067.out
109
--- a/Makefile.objs
32
+++ b/tests/qemu-iotests/067.out
110
+++ b/Makefile.objs
33
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
111
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
34
112
# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are
35
=== -drive/-device and device_del ===
113
# used for system emulation, too, but specified separately there)
36
114
37
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk,drive=disk,id=virtio0
115
-storage-daemon-obj-y = block/
38
+Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=disk -device virtio-blk,drive=disk,id=virtio0
116
+storage-daemon-obj-y = block/ qom/
39
{
117
storage-daemon-obj-y += blockdev.o iothread.o
40
QMP_VERSION
118
41
}
119
######################################################################
42
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
120
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
43
"detect_zeroes": "off",
121
index XXXXXXX..XXXXXXX 100644
44
"image": {
122
--- a/qom/Makefile.objs
45
"virtual-size": 134217728,
123
+++ b/qom/Makefile.objs
46
- "filename": "TEST_DIR/t.qcow2",
124
@@ -XXX,XX +XXX,XX @@ qom-obj-y = object.o container.o qom-qobject.o
47
+ "filename": "TEST_DIR/t.IMGFMT",
125
qom-obj-y += object_interfaces.o
48
"cluster-size": 65536,
126
49
- "format": "qcow2",
127
common-obj-$(CONFIG_SOFTMMU) += qom-hmp-cmds.o qom-qmp-cmds.o
50
+ "format": "IMGFMT",
128
+storage-daemon-obj-y += qom-qmp-cmds.o
51
"actual-size": SIZE,
52
- "format-specific": {
53
- "type": "qcow2",
54
- "data": {
55
- "compat": "1.1",
56
- "lazy-refcounts": false,
57
- "refcount-bits": 16,
58
- "corrupt": false
59
- }
60
- },
61
"dirty-flag": false
62
},
63
"iops_wr": 0,
64
"ro": false,
65
"node-name": "NODE_NAME",
66
"backing_file_depth": 0,
67
- "drv": "qcow2",
68
+ "drv": "IMGFMT",
69
"iops": 0,
70
"bps_wr": 0,
71
"write_threshold": 0,
72
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
73
"direct": false,
74
"writeback": true
75
},
76
- "file": "TEST_DIR/t.qcow2",
77
+ "file": "TEST_DIR/t.IMGFMT",
78
"encryption_key_missing": false
79
},
80
"qdev": "/machine/peripheral/virtio0/virtio-backend",
81
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
82
83
=== -drive/device_add and device_del ===
84
85
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
86
+Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=disk
87
{
88
QMP_VERSION
89
}
90
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
91
"detect_zeroes": "off",
92
"image": {
93
"virtual-size": 134217728,
94
- "filename": "TEST_DIR/t.qcow2",
95
+ "filename": "TEST_DIR/t.IMGFMT",
96
"cluster-size": 65536,
97
- "format": "qcow2",
98
+ "format": "IMGFMT",
99
"actual-size": SIZE,
100
- "format-specific": {
101
- "type": "qcow2",
102
- "data": {
103
- "compat": "1.1",
104
- "lazy-refcounts": false,
105
- "refcount-bits": 16,
106
- "corrupt": false
107
- }
108
- },
109
"dirty-flag": false
110
},
111
"iops_wr": 0,
112
"ro": false,
113
"node-name": "NODE_NAME",
114
"backing_file_depth": 0,
115
- "drv": "qcow2",
116
+ "drv": "IMGFMT",
117
"iops": 0,
118
"bps_wr": 0,
119
"write_threshold": 0,
120
@@ -XXX,XX +XXX,XX @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
121
"direct": false,
122
"writeback": true
123
},
124
- "file": "TEST_DIR/t.qcow2",
125
+ "file": "TEST_DIR/t.IMGFMT",
126
"encryption_key_missing": false
127
},
128
"type": "unknown"
129
@@ -XXX,XX +XXX,XX @@ Testing:
130
"detect_zeroes": "off",
131
"image": {
132
"virtual-size": 134217728,
133
- "filename": "TEST_DIR/t.qcow2",
134
+ "filename": "TEST_DIR/t.IMGFMT",
135
"cluster-size": 65536,
136
- "format": "qcow2",
137
+ "format": "IMGFMT",
138
"actual-size": SIZE,
139
- "format-specific": {
140
- "type": "qcow2",
141
- "data": {
142
- "compat": "1.1",
143
- "lazy-refcounts": false,
144
- "refcount-bits": 16,
145
- "corrupt": false
146
- }
147
- },
148
"dirty-flag": false
149
},
150
"iops_wr": 0,
151
"ro": false,
152
"node-name": "NODE_NAME",
153
"backing_file_depth": 0,
154
- "drv": "qcow2",
155
+ "drv": "IMGFMT",
156
"iops": 0,
157
"bps_wr": 0,
158
"write_threshold": 0,
159
@@ -XXX,XX +XXX,XX @@ Testing:
160
"direct": false,
161
"writeback": true
162
},
163
- "file": "TEST_DIR/t.qcow2",
164
+ "file": "TEST_DIR/t.IMGFMT",
165
"encryption_key_missing": false
166
},
167
"type": "unknown"
168
@@ -XXX,XX +XXX,XX @@ Testing:
169
"detect_zeroes": "off",
170
"image": {
171
"virtual-size": 134217728,
172
- "filename": "TEST_DIR/t.qcow2",
173
+ "filename": "TEST_DIR/t.IMGFMT",
174
"cluster-size": 65536,
175
- "format": "qcow2",
176
+ "format": "IMGFMT",
177
"actual-size": SIZE,
178
- "format-specific": {
179
- "type": "qcow2",
180
- "data": {
181
- "compat": "1.1",
182
- "lazy-refcounts": false,
183
- "refcount-bits": 16,
184
- "corrupt": false
185
- }
186
- },
187
"dirty-flag": false
188
},
189
"iops_wr": 0,
190
"ro": false,
191
"node-name": "disk",
192
"backing_file_depth": 0,
193
- "drv": "qcow2",
194
+ "drv": "IMGFMT",
195
"iops": 0,
196
"bps_wr": 0,
197
"write_threshold": 0,
198
@@ -XXX,XX +XXX,XX @@ Testing:
199
"direct": false,
200
"writeback": true
201
},
202
- "file": "TEST_DIR/t.qcow2",
203
+ "file": "TEST_DIR/t.IMGFMT",
204
"encryption_key_missing": false
205
},
206
{
207
@@ -XXX,XX +XXX,XX @@ Testing:
208
"detect_zeroes": "off",
209
"image": {
210
"virtual-size": 197120,
211
- "filename": "TEST_DIR/t.qcow2",
212
+ "filename": "TEST_DIR/t.IMGFMT",
213
"format": "file",
214
"actual-size": SIZE,
215
"dirty-flag": false
216
@@ -XXX,XX +XXX,XX @@ Testing:
217
"direct": false,
218
"writeback": true
219
},
220
- "file": "TEST_DIR/t.qcow2",
221
+ "file": "TEST_DIR/t.IMGFMT",
222
"encryption_key_missing": false
223
}
224
]
225
@@ -XXX,XX +XXX,XX @@ Testing:
226
"detect_zeroes": "off",
227
"image": {
228
"virtual-size": 134217728,
229
- "filename": "TEST_DIR/t.qcow2",
230
+ "filename": "TEST_DIR/t.IMGFMT",
231
"cluster-size": 65536,
232
- "format": "qcow2",
233
+ "format": "IMGFMT",
234
"actual-size": SIZE,
235
- "format-specific": {
236
- "type": "qcow2",
237
- "data": {
238
- "compat": "1.1",
239
- "lazy-refcounts": false,
240
- "refcount-bits": 16,
241
- "corrupt": false
242
- }
243
- },
244
"dirty-flag": false
245
},
246
"iops_wr": 0,
247
"ro": false,
248
"node-name": "disk",
249
"backing_file_depth": 0,
250
- "drv": "qcow2",
251
+ "drv": "IMGFMT",
252
"iops": 0,
253
"bps_wr": 0,
254
"write_threshold": 0,
255
@@ -XXX,XX +XXX,XX @@ Testing:
256
"direct": false,
257
"writeback": true
258
},
259
- "file": "TEST_DIR/t.qcow2",
260
+ "file": "TEST_DIR/t.IMGFMT",
261
"encryption_key_missing": false
262
},
263
{
264
@@ -XXX,XX +XXX,XX @@ Testing:
265
"detect_zeroes": "off",
266
"image": {
267
"virtual-size": 197120,
268
- "filename": "TEST_DIR/t.qcow2",
269
+ "filename": "TEST_DIR/t.IMGFMT",
270
"format": "file",
271
"actual-size": SIZE,
272
"dirty-flag": false
273
@@ -XXX,XX +XXX,XX @@ Testing:
274
"direct": false,
275
"writeback": true
276
},
277
- "file": "TEST_DIR/t.qcow2",
278
+ "file": "TEST_DIR/t.IMGFMT",
279
"encryption_key_missing": false
280
}
281
]
282
--
129
--
283
2.13.6
130
2.20.1
284
131
285
132
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Add a --nbd-server option to qemu-storage-daemon to start the built-in
2
NBD server right away. It maps the arguments for nbd-server-start to the
3
command line, with the exception that it uses SocketAddress instead of
4
SocketAddressLegacy: New interfaces shouldn't use legacy types, and the
5
additional nesting would be nasty on the command line.
2
6
3
This is an incompatible change, which is fine as the commands are
7
Example (only with required options):
4
experimental.
5
8
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
--nbd-server addr.type=inet,addr.host=localhost,addr.port=10809
7
Message-id: 20171110224302.14424-4-mreitz@redhat.com
10
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200224143008.13362-10-kwolf@redhat.com>
13
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
qapi/block-core.json | 10 ++--------
16
qapi/block-core.json | 24 ++++++++++++++++++++++++
12
blockdev.c | 30 +++++++++++++++++++++++-------
17
include/block/nbd.h | 1 +
13
2 files changed, 25 insertions(+), 15 deletions(-)
18
blockdev-nbd.c | 5 +++++
19
qemu-storage-daemon.c | 26 +++++++++++++++++++++++++-
20
Makefile.objs | 2 +-
21
5 files changed, 56 insertions(+), 2 deletions(-)
14
22
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
16
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
17
--- a/qapi/block-core.json
25
--- a/qapi/block-core.json
18
+++ b/qapi/block-core.json
26
+++ b/qapi/block-core.json
19
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
28
'iothread': 'StrOrNull',
29
'*force': 'bool' } }
30
31
+##
32
+# @NbdServerOptions:
33
+#
34
+# @addr: Address on which to listen.
35
+# @tls-creds: ID of the TLS credentials object (since 2.6).
36
+# @tls-authz: ID of the QAuthZ authorization object used to validate
37
+# the client's x509 distinguished name. This object is
38
+# is only resolved at time of use, so can be deleted and
39
+# recreated on the fly while the NBD server is active.
40
+# If missing, it will default to denying access (since 4.0).
41
+#
42
+# Keep this type consistent with the nbd-server-start arguments. The only
43
+# intended difference is using SocketAddress instead of SocketAddressLegacy.
44
+#
45
+# Since: 4.2
46
+##
47
+{ 'struct': 'NbdServerOptions',
48
+ 'data': { 'addr': 'SocketAddress',
49
+ '*tls-creds': 'str',
50
+ '*tls-authz': 'str'} }
51
+
52
##
53
# @nbd-server-start:
20
#
54
#
21
# If the tray is open and there is no medium inserted, this will be a no-op.
22
#
23
-# @device: Block device name (deprecated, use @id instead)
24
-#
25
# @id: The name or QOM path of the guest device (since: 2.8)
26
#
27
# Note: This command is still a work in progress and is considered experimental.
28
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@
29
#
56
#
57
# Returns: error if the server is already running.
58
#
59
+# Keep this type consistent with the NbdServerOptions type. The only intended
60
+# difference is using SocketAddressLegacy instead of SocketAddress.
61
+#
62
# Since: 1.3.0
30
##
63
##
31
{ 'command': 'x-blockdev-remove-medium',
64
{ 'command': 'nbd-server-start',
32
- 'data': { '*device': 'str',
65
diff --git a/include/block/nbd.h b/include/block/nbd.h
33
- '*id': 'str' } }
34
+ 'data': { 'id': 'str' } }
35
36
##
37
# @x-blockdev-insert-medium:
38
@@ -XXX,XX +XXX,XX @@
39
# device's tray must currently be open (unless there is no attached guest
40
# device) and there must be no medium inserted already.
41
#
42
-# @device: Block device name (deprecated, use @id instead)
43
-#
44
# @id: The name or QOM path of the guest device (since: 2.8)
45
#
46
# @node-name: name of a node in the block driver state graph
47
@@ -XXX,XX +XXX,XX @@
48
#
49
##
50
{ 'command': 'x-blockdev-insert-medium',
51
- 'data': { '*device': 'str',
52
- '*id': 'str',
53
+ 'data': { 'id': 'str',
54
'node-name': 'str'} }
55
56
57
diff --git a/blockdev.c b/blockdev.c
58
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
59
--- a/blockdev.c
67
--- a/include/block/nbd.h
60
+++ b/blockdev.c
68
+++ b/include/block/nbd.h
61
@@ -XXX,XX +XXX,XX @@ static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
69
@@ -XXX,XX +XXX,XX @@ void nbd_client_put(NBDClient *client);
62
70
63
static int do_open_tray(const char *blk_name, const char *qdev_id,
71
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
64
bool force, Error **errp);
72
const char *tls_authz, Error **errp);
65
+static void blockdev_remove_medium(bool has_device, const char *device,
73
+void nbd_server_start_options(NbdServerOptions *arg, Error **errp);
66
+ bool has_id, const char *id, Error **errp);
74
67
+static void blockdev_insert_medium(bool has_device, const char *device,
75
/* nbd_read
68
+ bool has_id, const char *id,
76
* Reads @size bytes from @ioc. Returns 0 on success.
69
+ const char *node_name, Error **errp);
77
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
70
78
index XXXXXXX..XXXXXXX 100644
71
static const char *const if_name[IF_COUNT] = {
79
--- a/blockdev-nbd.c
72
[IF_NONE] = "none",
80
+++ b/blockdev-nbd.c
73
@@ -XXX,XX +XXX,XX @@ void qmp_eject(bool has_device, const char *device,
81
@@ -XXX,XX +XXX,XX @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
74
}
82
nbd_server = NULL;
75
error_free(local_err);
76
77
- qmp_x_blockdev_remove_medium(has_device, device, has_id, id, errp);
78
+ blockdev_remove_medium(has_device, device, has_id, id, errp);
79
}
83
}
80
84
81
void qmp_block_passwd(bool has_device, const char *device,
85
+void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
82
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_close_tray(bool has_device, const char *device,
83
}
84
}
85
86
-void qmp_x_blockdev_remove_medium(bool has_device, const char *device,
87
- bool has_id, const char *id, Error **errp)
88
+static void blockdev_remove_medium(bool has_device, const char *device,
89
+ bool has_id, const char *id, Error **errp)
90
{
91
BlockBackend *blk;
92
BlockDriverState *bs;
93
@@ -XXX,XX +XXX,XX @@ out:
94
aio_context_release(aio_context);
95
}
96
97
+void qmp_x_blockdev_remove_medium(const char *id, Error **errp)
98
+{
86
+{
99
+ blockdev_remove_medium(false, NULL, true, id, errp);
87
+ nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, errp);
100
+}
88
+}
101
+
89
+
102
static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
90
void qmp_nbd_server_start(SocketAddressLegacy *addr,
103
BlockDriverState *bs, Error **errp)
91
bool has_tls_creds, const char *tls_creds,
104
{
92
bool has_tls_authz, const char *tls_authz,
105
@@ -XXX,XX +XXX,XX @@ static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
93
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
106
}
94
index XXXXXXX..XXXXXXX 100644
107
}
95
--- a/qemu-storage-daemon.c
108
96
+++ b/qemu-storage-daemon.c
109
-void qmp_x_blockdev_insert_medium(bool has_device, const char *device,
97
@@ -XXX,XX +XXX,XX @@
110
- bool has_id, const char *id,
98
#include <getopt.h>
111
- const char *node_name, Error **errp)
99
112
+static void blockdev_insert_medium(bool has_device, const char *device,
100
#include "block/block.h"
113
+ bool has_id, const char *id,
101
+#include "block/nbd.h"
114
+ const char *node_name, Error **errp)
102
#include "crypto/init.h"
115
{
103
116
BlockBackend *blk;
104
#include "qapi/error.h"
117
BlockDriverState *bs;
105
-#include "qapi/qapi-visit-block-core.h"
118
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_insert_medium(bool has_device, const char *device,
106
+#include "qapi/qapi-commands-block.h"
119
qmp_blockdev_insert_anon_medium(blk, bs, errp);
107
#include "qapi/qapi-commands-block-core.h"
120
}
108
+#include "qapi/qapi-visit-block.h"
121
109
+#include "qapi/qapi-visit-block-core.h"
122
+void qmp_x_blockdev_insert_medium(const char *id, const char *node_name,
110
#include "qapi/qmp/qdict.h"
123
+ Error **errp)
111
#include "qapi/qobject-input-visitor.h"
124
+{
112
125
+ blockdev_insert_medium(false, NULL, true, id, node_name, errp);
113
@@ -XXX,XX +XXX,XX @@ static void help(void)
126
+}
114
" [,driver specific parameters...]\n"
115
" configure a block backend\n"
116
"\n"
117
+" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
118
+" [,tls-creds=<id>][,tls-authz=<id>]\n"
119
+" --nbd-server addr.type=unix,addr.path=<path>\n"
120
+" [,tls-creds=<id>][,tls-authz=<id>]\n"
121
+" start an NBD server for exporting block nodes\n"
122
+"\n"
123
" --object help list object types that can be added\n"
124
" --object <type>,help list properties for the given object type\n"
125
" --object <type>[,<property>=<value>...]\n"
126
@@ -XXX,XX +XXX,XX @@ QEMU_HELP_BOTTOM "\n",
127
128
enum {
129
OPTION_BLOCKDEV = 256,
130
+ OPTION_NBD_SERVER,
131
OPTION_OBJECT,
132
};
133
134
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
135
static const struct option long_options[] = {
136
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
137
{"help", no_argument, NULL, 'h'},
138
+ {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
139
{"object", required_argument, NULL, OPTION_OBJECT},
140
{"trace", required_argument, NULL, 'T'},
141
{"version", no_argument, NULL, 'V'},
142
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
143
qapi_free_BlockdevOptions(options);
144
break;
145
}
146
+ case OPTION_NBD_SERVER:
147
+ {
148
+ Visitor *v;
149
+ NbdServerOptions *options;
127
+
150
+
128
void qmp_blockdev_change_medium(bool has_device, const char *device,
151
+ v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
129
bool has_id, const char *id,
152
+ visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
130
const char *filename,
153
+ visit_free(v);
131
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
154
+
132
error_free(err);
155
+ nbd_server_start_options(options, &error_fatal);
133
err = NULL;
156
+ qapi_free_NbdServerOptions(options);
134
157
+ break;
135
- qmp_x_blockdev_remove_medium(has_device, device, has_id, id, &err);
158
+ }
136
+ blockdev_remove_medium(has_device, device, has_id, id, &err);
159
case OPTION_OBJECT:
137
if (err) {
160
{
138
error_propagate(errp, err);
161
QemuOpts *opts;
139
goto fail;
162
diff --git a/Makefile.objs b/Makefile.objs
163
index XXXXXXX..XXXXXXX 100644
164
--- a/Makefile.objs
165
+++ b/Makefile.objs
166
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
167
# used for system emulation, too, but specified separately there)
168
169
storage-daemon-obj-y = block/ qom/
170
-storage-daemon-obj-y += blockdev.o iothread.o
171
+storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o
172
173
######################################################################
174
# Target independent part of system emulation. The long term path is to
140
--
175
--
141
2.13.6
176
2.20.1
142
177
143
178
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Move the arguments of nbd-server-add to a new struct BlockExportNbd and
2
convert the command to 'boxed': true. This makes it easier to share code
3
with the storage daemon.
2
4
3
Now that iotest 093 test proves that the throttling configuration
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
survives a blockdev-remove-medium/blockdev-insert-medium pair, the
6
Message-Id: <20200224143008.13362-11-kwolf@redhat.com>
5
original reason for declaring these commands experimental is gone
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
6
(see commit 6e0abc251dd4f8eba1f53656dfede12e5840e83b).
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Message-id: 20171110224302.14424-5-mreitz@redhat.com
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
9
---
13
qapi/block-core.json | 32 +++++++++++++-------------------
10
qapi/block-core.json | 18 ++++++++++++++----
14
blockdev.c | 6 +++---
11
blockdev-nbd.c | 35 ++++++++++++++++-------------------
15
tests/ahci-test.c | 4 ++--
12
monitor/hmp-cmds.c | 21 +++++++++++++++++----
16
tests/qemu-iotests/093 | 6 +++---
13
3 files changed, 47 insertions(+), 27 deletions(-)
17
tests/qemu-iotests/118 | 20 ++++++++++----------
18
tests/qemu-iotests/139 | 2 +-
19
6 files changed, 32 insertions(+), 38 deletions(-)
20
14
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/block-core.json
17
--- a/qapi/block-core.json
24
+++ b/qapi/block-core.json
18
+++ b/qapi/block-core.json
25
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
26
'*id': 'str' } }
20
'*tls-authz': 'str'} }
27
21
28
##
22
##
29
-# @x-blockdev-remove-medium:
23
-# @nbd-server-add:
30
+# @blockdev-remove-medium:
24
+# @BlockExportNbd:
31
#
25
#
32
# Removes a medium (a block driver state tree) from a block device. That block
26
-# Export a block node to QEMU's embedded NBD server.
33
# device's tray must currently be open (unless there is no attached guest
27
+# An NBD block export.
34
@@ -XXX,XX +XXX,XX @@
35
#
28
#
36
# If the tray is open and there is no medium inserted, this will be a no-op.
29
# @device: The device name or node name of the node to be exported
37
#
38
-# @id: The name or QOM path of the guest device (since: 2.8)
39
-#
40
-# Note: This command is still a work in progress and is considered experimental.
41
-# Stay away from it unless you want to help with its development.
42
+# @id: The name or QOM path of the guest device
43
#
44
-# Since: 2.5
45
+# Since: 2.12
46
#
47
# Example:
48
#
49
-# -> { "execute": "x-blockdev-remove-medium",
50
+# -> { "execute": "blockdev-remove-medium",
51
# "arguments": { "id": "ide0-1-0" } }
52
#
53
# <- { "error": { "class": "GenericError",
54
@@ -XXX,XX +XXX,XX @@
55
#
56
# <- { "return": {} }
57
#
58
-# -> { "execute": "x-blockdev-remove-medium",
59
+# -> { "execute": "blockdev-remove-medium",
60
# "arguments": { "id": "ide0-1-0" } }
61
#
62
# <- { "return": {} }
63
#
64
##
65
-{ 'command': 'x-blockdev-remove-medium',
66
+{ 'command': 'blockdev-remove-medium',
67
'data': { 'id': 'str' } }
68
69
##
70
-# @x-blockdev-insert-medium:
71
+# @blockdev-insert-medium:
72
#
73
# Inserts a medium (a block driver state tree) into a block device. That block
74
# device's tray must currently be open (unless there is no attached guest
75
# device) and there must be no medium inserted already.
76
#
77
-# @id: The name or QOM path of the guest device (since: 2.8)
78
+# @id: The name or QOM path of the guest device
79
#
80
# @node-name: name of a node in the block driver state graph
81
#
82
-# Note: This command is still a work in progress and is considered experimental.
83
-# Stay away from it unless you want to help with its development.
84
-#
85
-# Since: 2.5
86
+# Since: 2.12
87
#
88
# Example:
89
#
30
#
90
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
91
# "filename": "fedora.iso" } } }
32
# NBD client can use NBD_OPT_SET_META_CONTEXT with
92
# <- { "return": {} }
33
# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
93
#
34
#
94
-# -> { "execute": "x-blockdev-insert-medium",
35
+# Since: 5.0
95
+# -> { "execute": "blockdev-insert-medium",
36
+##
96
# "arguments": { "id": "ide0-1-0",
37
+{ 'struct': 'BlockExportNbd',
97
# "node-name": "node0" } }
38
+ 'data': {'device': 'str', '*name': 'str', '*description': 'str',
39
+ '*writable': 'bool', '*bitmap': 'str' } }
40
+
41
+##
42
+# @nbd-server-add:
43
+#
44
+# Export a block node to QEMU's embedded NBD server.
45
+#
46
# Returns: error if the server is not running, or export with the same name
47
# already exists.
98
#
48
#
99
# <- { "return": {} }
49
# Since: 1.3.0
100
#
101
##
50
##
102
-{ 'command': 'x-blockdev-insert-medium',
51
{ 'command': 'nbd-server-add',
103
+{ 'command': 'blockdev-insert-medium',
52
- 'data': {'device': 'str', '*name': 'str', '*description': 'str',
104
'data': { 'id': 'str',
53
- '*writable': 'bool', '*bitmap': 'str' } }
105
'node-name': 'str'} }
54
+ 'data': 'BlockExportNbd', 'boxed': true }
106
55
107
@@ -XXX,XX +XXX,XX @@
56
##
108
#
57
# @NbdServerRemoveMode:
109
# Changes the medium inserted into a block device by ejecting the current medium
58
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
110
# and loading a new image file which is inserted as the new medium (this command
111
-# combines blockdev-open-tray, x-blockdev-remove-medium,
112
-# x-blockdev-insert-medium and blockdev-close-tray).
113
+# combines blockdev-open-tray, blockdev-remove-medium, blockdev-insert-medium
114
+# and blockdev-close-tray).
115
#
116
# @device: Block device name (deprecated, use @id instead)
117
#
118
diff --git a/blockdev.c b/blockdev.c
119
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
120
--- a/blockdev.c
60
--- a/blockdev-nbd.c
121
+++ b/blockdev.c
61
+++ b/blockdev-nbd.c
122
@@ -XXX,XX +XXX,XX @@ out:
62
@@ -XXX,XX +XXX,XX @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
123
aio_context_release(aio_context);
63
qapi_free_SocketAddress(addr_flat);
124
}
64
}
125
65
126
-void qmp_x_blockdev_remove_medium(const char *id, Error **errp)
66
-void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
127
+void qmp_blockdev_remove_medium(const char *id, Error **errp)
67
- bool has_description, const char *description,
68
- bool has_writable, bool writable,
69
- bool has_bitmap, const char *bitmap, Error **errp)
70
+void qmp_nbd_server_add(BlockExportNbd *arg, Error **errp)
128
{
71
{
129
blockdev_remove_medium(false, NULL, true, id, errp);
72
BlockDriverState *bs = NULL;
73
BlockBackend *on_eject_blk;
74
@@ -XXX,XX +XXX,XX @@ void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
75
return;
76
}
77
78
- if (!has_name) {
79
- name = device;
80
+ if (!arg->has_name) {
81
+ arg->name = arg->device;
82
}
83
84
- if (strlen(name) > NBD_MAX_STRING_SIZE) {
85
- error_setg(errp, "export name '%s' too long", name);
86
+ if (strlen(arg->name) > NBD_MAX_STRING_SIZE) {
87
+ error_setg(errp, "export name '%s' too long", arg->name);
88
return;
89
}
90
91
- if (has_description && strlen(description) > NBD_MAX_STRING_SIZE) {
92
- error_setg(errp, "description '%s' too long", description);
93
+ if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) {
94
+ error_setg(errp, "description '%s' too long", arg->description);
95
return;
96
}
97
98
- if (nbd_export_find(name)) {
99
- error_setg(errp, "NBD server already has export named '%s'", name);
100
+ if (nbd_export_find(arg->name)) {
101
+ error_setg(errp, "NBD server already has export named '%s'", arg->name);
102
return;
103
}
104
105
- on_eject_blk = blk_by_name(device);
106
+ on_eject_blk = blk_by_name(arg->device);
107
108
- bs = bdrv_lookup_bs(device, device, errp);
109
+ bs = bdrv_lookup_bs(arg->device, arg->device, errp);
110
if (!bs) {
111
return;
112
}
113
@@ -XXX,XX +XXX,XX @@ void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
114
goto out;
115
}
116
117
- if (!has_writable) {
118
- writable = false;
119
+ if (!arg->has_writable) {
120
+ arg->writable = false;
121
}
122
if (bdrv_is_read_only(bs)) {
123
- writable = false;
124
+ arg->writable = false;
125
}
126
127
- exp = nbd_export_new(bs, 0, len, name, description, bitmap,
128
- !writable, !writable,
129
+ exp = nbd_export_new(bs, 0, len, arg->name, arg->description, arg->bitmap,
130
+ !arg->writable, !arg->writable,
131
NULL, false, on_eject_blk, errp);
132
if (!exp) {
133
goto out;
134
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/monitor/hmp-cmds.c
137
+++ b/monitor/hmp-cmds.c
138
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
139
Error *local_err = NULL;
140
BlockInfoList *block_list, *info;
141
SocketAddress *addr;
142
+ BlockExportNbd export;
143
144
if (writable && !all) {
145
error_setg(&local_err, "-w only valid together with -a");
146
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
147
continue;
148
}
149
150
- qmp_nbd_server_add(info->value->device, false, NULL, false, NULL,
151
- true, writable, false, NULL, &local_err);
152
+ export = (BlockExportNbd) {
153
+ .device = info->value->device,
154
+ .has_writable = true,
155
+ .writable = writable,
156
+ };
157
+
158
+ qmp_nbd_server_add(&export, &local_err);
159
160
if (local_err != NULL) {
161
qmp_nbd_server_stop(NULL);
162
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict)
163
bool writable = qdict_get_try_bool(qdict, "writable", false);
164
Error *local_err = NULL;
165
166
- qmp_nbd_server_add(device, !!name, name, false, NULL, true, writable,
167
- false, NULL, &local_err);
168
+ BlockExportNbd export = {
169
+ .device = (char *) device,
170
+ .has_name = !!name,
171
+ .name = (char *) name,
172
+ .has_writable = true,
173
+ .writable = writable,
174
+ };
175
+
176
+ qmp_nbd_server_add(&export, &local_err);
177
hmp_handle_error(mon, local_err);
130
}
178
}
131
@@ -XXX,XX +XXX,XX @@ static void blockdev_insert_medium(bool has_device, const char *device,
179
132
qmp_blockdev_insert_anon_medium(blk, bs, errp);
133
}
134
135
-void qmp_x_blockdev_insert_medium(const char *id, const char *node_name,
136
- Error **errp)
137
+void qmp_blockdev_insert_medium(const char *id, const char *node_name,
138
+ Error **errp)
139
{
140
blockdev_insert_medium(false, NULL, true, id, node_name, errp);
141
}
142
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/tests/ahci-test.c
145
+++ b/tests/ahci-test.c
146
@@ -XXX,XX +XXX,XX @@ static void test_atapi_tray(void)
147
rsp = qmp_receive();
148
QDECREF(rsp);
149
150
- qmp_discard_response("{'execute': 'x-blockdev-remove-medium', "
151
+ qmp_discard_response("{'execute': 'blockdev-remove-medium', "
152
"'arguments': {'id': 'cd0'}}");
153
154
/* Test the tray without a medium */
155
@@ -XXX,XX +XXX,XX @@ static void test_atapi_tray(void)
156
"'driver': 'raw', "
157
"'file': { 'driver': 'file', "
158
"'filename': %s }}}", iso);
159
- qmp_discard_response("{'execute': 'x-blockdev-insert-medium',"
160
+ qmp_discard_response("{'execute': 'blockdev-insert-medium',"
161
"'arguments': { 'id': 'cd0', "
162
"'node-name': 'node0' }}");
163
164
diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093
165
index XXXXXXX..XXXXXXX 100755
166
--- a/tests/qemu-iotests/093
167
+++ b/tests/qemu-iotests/093
168
@@ -XXX,XX +XXX,XX @@ class ThrottleTestRemovableMedia(iotests.QMPTestCase):
169
# Now eject cd0 and insert cd1
170
result = self.vm.qmp("blockdev-open-tray", id='dev0')
171
self.assert_qmp(result, 'return', {})
172
- result = self.vm.qmp("x-blockdev-remove-medium", id='dev0')
173
+ result = self.vm.qmp("blockdev-remove-medium", id='dev0')
174
self.assert_qmp(result, 'return', {})
175
- result = self.vm.qmp("x-blockdev-insert-medium", id='dev0', node_name='cd1')
176
+ result = self.vm.qmp("blockdev-insert-medium", id='dev0', node_name='cd1')
177
self.assert_qmp(result, 'return', {})
178
179
# Check that the I/O limits are still the same
180
@@ -XXX,XX +XXX,XX @@ class ThrottleTestRemovableMedia(iotests.QMPTestCase):
181
self.assert_qmp(result, 'return[0]/inserted/bps', 50)
182
183
# Eject cd1
184
- result = self.vm.qmp("x-blockdev-remove-medium", id='dev0')
185
+ result = self.vm.qmp("blockdev-remove-medium", id='dev0')
186
self.assert_qmp(result, 'return', {})
187
188
# Check that we can't set limits if the device has no medium
189
diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
190
index XXXXXXX..XXXXXXX 100755
191
--- a/tests/qemu-iotests/118
192
+++ b/tests/qemu-iotests/118
193
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
194
else:
195
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
196
197
- result = self.vm.qmp('x-blockdev-remove-medium',
198
+ result = self.vm.qmp('blockdev-remove-medium',
199
id=self.device_name)
200
self.assert_qmp(result, 'return', {})
201
202
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
203
self.assert_qmp(result, 'return[0]/tray_open', True)
204
self.assert_qmp_absent(result, 'return[0]/inserted')
205
206
- result = self.vm.qmp('x-blockdev-insert-medium',
207
+ result = self.vm.qmp('blockdev-insert-medium',
208
id=self.device_name, node_name='new')
209
self.assert_qmp(result, 'return', {})
210
211
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
212
if not self.has_real_tray:
213
return
214
215
- result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
216
+ result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
217
self.assert_qmp(result, 'error/class', 'GenericError')
218
219
def test_insert_on_closed(self):
220
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
221
'driver': 'file'})
222
self.assert_qmp(result, 'return', {})
223
224
- result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
225
+ result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
226
node_name='new')
227
self.assert_qmp(result, 'error/class', 'GenericError')
228
229
@@ -XXX,XX +XXX,XX @@ class TestInitiallyFilled(GeneralChangeTestsBaseClass):
230
231
self.wait_for_open()
232
233
- result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
234
+ result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
235
node_name='new')
236
self.assert_qmp(result, 'error/class', 'GenericError')
237
238
@@ -XXX,XX +XXX,XX @@ class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
239
240
self.wait_for_open()
241
242
- result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
243
+ result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
244
# Should be a no-op
245
self.assert_qmp(result, 'return', {})
246
247
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
248
self.assert_qmp(result, 'return[0]/inserted/ro', False)
249
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
250
251
- result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
252
+ result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
253
self.assert_qmp(result, 'return', {})
254
255
result = self.vm.qmp('query-block')
256
self.assert_qmp_absent(result, 'return[0]/inserted')
257
258
- result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
259
+ result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
260
node_name='new')
261
self.assert_qmp(result, 'return', {})
262
263
@@ -XXX,XX +XXX,XX @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
264
265
# For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
266
# is not necessary
267
- result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
268
+ result = self.vm.qmp('blockdev-remove-medium', id=self.device_name)
269
self.assert_qmp(result, 'return', {})
270
271
result = self.vm.qmp('query-block')
272
@@ -XXX,XX +XXX,XX @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
273
'driver': 'file'})
274
self.assert_qmp(result, 'return', {})
275
276
- result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
277
+ result = self.vm.qmp('blockdev-insert-medium', id=self.device_name,
278
node_name='node0')
279
self.assert_qmp(result, 'return', {})
280
281
diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
282
index XXXXXXX..XXXXXXX 100644
283
--- a/tests/qemu-iotests/139
284
+++ b/tests/qemu-iotests/139
285
@@ -XXX,XX +XXX,XX @@ class TestBlockdevDel(iotests.QMPTestCase):
286
# Insert a BlockDriverState
287
def insertDrive(self, device, node):
288
self.checkBlockDriverState(node)
289
- result = self.vm.qmp('x-blockdev-insert-medium',
290
+ result = self.vm.qmp('blockdev-insert-medium',
291
id = device, node_name = node)
292
self.assert_qmp(result, 'return', {})
293
self.checkBlockDriverState(node)
294
--
180
--
295
2.13.6
181
2.20.1
296
182
297
183
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Add a --export option to qemu-storage-daemon to export a block node. For
2
now, only NBD exports are implemented. Apart from the 'type' option
3
(which is the implied key), it maps the arguments for nbd-server-add to
4
the command line. Example:
2
5
3
102 truncates a qcow2 file (the raw file) on purpose while a VM is
6
--export nbd,device=disk,name=test-export,writable=on
4
running. However, image locking will usually prevent exactly this.
5
7
6
The fact that most people have not noticed until now (I suppose you may
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
have seen sporadic failures, but not taken them too seriously, like me)
9
Message-Id: <20200224143008.13362-12-kwolf@redhat.com>
8
further shows that this truncation is actually not really done
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9
concurrently, but that the VM is still starting up by this point and has
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
not yet opened the image. Remedy this by waiting for the monitor shell
12
---
11
to appear before the qemu-img invocation so we know the VM is up.
13
qapi/block-core.json | 27 +++++++++++++++++++++++++++
14
qemu-storage-daemon.c | 31 +++++++++++++++++++++++++++++++
15
2 files changed, 58 insertions(+)
12
16
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
Message-id: 20171129185102.29390-1-mreitz@redhat.com
18
index XXXXXXX..XXXXXXX 100644
15
Reviewed-by: Eric Blake <eblake@redhat.com>
19
--- a/qapi/block-core.json
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
+++ b/qapi/block-core.json
17
---
21
@@ -XXX,XX +XXX,XX @@
18
tests/qemu-iotests/102 | 7 ++++++-
22
##
19
tests/qemu-iotests/102.out | 3 ++-
23
{ 'command': 'nbd-server-stop' }
20
2 files changed, 8 insertions(+), 2 deletions(-)
24
21
25
+##
22
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
26
+# @BlockExportType:
23
index XXXXXXX..XXXXXXX 100755
27
+#
24
--- a/tests/qemu-iotests/102
28
+# An enumeration of block export types
25
+++ b/tests/qemu-iotests/102
29
+#
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
30
+# @nbd: NBD export
27
31
+#
28
qemu_comm_method=monitor _launch_qemu -drive if=none,file="$TEST_IMG",id=drv0
32
+# Since: 4.2
29
33
+##
30
-$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))
34
+{ 'enum': 'BlockExportType',
31
+# Wait for a prompt to appear (so we know qemu has opened the image)
35
+ 'data': [ 'nbd' ] }
32
+_send_qemu_cmd '' '(qemu)'
33
+
36
+
34
+$QEMU_IMG resize --shrink --image-opts \
37
+##
35
+ "driver=raw,file.driver=file,file.filename=$TEST_IMG,file.locking=off" \
38
+# @BlockExport:
36
+ $((5 * 64 * 1024))
39
+#
37
40
+# Describes a block export, i.e. how single node should be exported on an
38
_send_qemu_cmd $QEMU_HANDLE 'qemu-io drv0 map' 'allocated' \
41
+# external interface.
39
| sed -e 's/^(qemu).*qemu-io drv0 map...$/(qemu) qemu-io drv0 map/'
42
+#
40
diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out
43
+# Since: 4.2
44
+##
45
+{ 'union': 'BlockExport',
46
+ 'base': { 'type': 'BlockExportType' },
47
+ 'discriminator': 'type',
48
+ 'data': {
49
+ 'nbd': 'BlockExportNbd'
50
+ } }
51
+
52
##
53
# @QuorumOpType:
54
#
55
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
41
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/102.out
57
--- a/qemu-storage-daemon.c
43
+++ b/tests/qemu-iotests/102.out
58
+++ b/qemu-storage-daemon.c
44
@@ -XXX,XX +XXX,XX @@ Offset Length Mapped to File
59
@@ -XXX,XX +XXX,XX @@ static void help(void)
45
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
60
" [,driver specific parameters...]\n"
46
wrote 65536/65536 bytes at offset 0
61
" configure a block backend\n"
47
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
62
"\n"
48
-Image resized.
63
+" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
49
QEMU X.Y.Z monitor - type 'help' for more information
64
+" [,writable=on|off][,bitmap=<name>]\n"
50
+Image resized.
65
+" export the specified block node over NBD\n"
51
+(qemu)
66
+" (requires --nbd-server)\n"
52
(qemu) qemu-io drv0 map
67
+"\n"
53
64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
68
" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
54
*** done
69
" [,tls-creds=<id>][,tls-authz=<id>]\n"
70
" --nbd-server addr.type=unix,addr.path=<path>\n"
71
@@ -XXX,XX +XXX,XX @@ QEMU_HELP_BOTTOM "\n",
72
73
enum {
74
OPTION_BLOCKDEV = 256,
75
+ OPTION_EXPORT,
76
OPTION_NBD_SERVER,
77
OPTION_OBJECT,
78
};
79
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_object_opts = {
80
},
81
};
82
83
+static void init_export(BlockExport *export, Error **errp)
84
+{
85
+ switch (export->type) {
86
+ case BLOCK_EXPORT_TYPE_NBD:
87
+ qmp_nbd_server_add(&export->u.nbd, errp);
88
+ break;
89
+ default:
90
+ g_assert_not_reached();
91
+ }
92
+}
93
+
94
static void process_options(int argc, char *argv[])
95
{
96
int c;
97
98
static const struct option long_options[] = {
99
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
100
+ {"export", required_argument, NULL, OPTION_EXPORT},
101
{"help", no_argument, NULL, 'h'},
102
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
103
{"object", required_argument, NULL, OPTION_OBJECT},
104
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
105
qapi_free_BlockdevOptions(options);
106
break;
107
}
108
+ case OPTION_EXPORT:
109
+ {
110
+ Visitor *v;
111
+ BlockExport *export;
112
+
113
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
114
+ visit_type_BlockExport(v, NULL, &export, &error_fatal);
115
+ visit_free(v);
116
+
117
+ init_export(export, &error_fatal);
118
+ qapi_free_BlockExport(export);
119
+ break;
120
+ }
121
case OPTION_NBD_SERVER:
122
{
123
Visitor *v;
55
--
124
--
56
2.13.6
125
2.20.1
57
126
58
127
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Instead of exiting after processing all command line options, start a
2
main loop and keep processing events until exit is requested with a
3
signal (e.g. SIGINT).
2
4
3
Currently, the tray and medium commands in the AHCI test use the
5
Now qemu-storage-daemon can be used as an alternative for qemu-nbd that
4
deprecated @device parameter. This patch switches all invocations over
6
provides a few features that were previously only available from QMP,
5
to use @id.
7
such as access to options only available with -blockdev and the socket
8
types 'vsock' and 'fd'.
6
9
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-id: 20171110224302.14424-3-mreitz@redhat.com
11
Message-Id: <20200224143008.13362-13-kwolf@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
14
---
12
tests/ahci-test.c | 12 ++++++------
15
qemu-storage-daemon.c | 13 +++++++++++++
13
1 file changed, 6 insertions(+), 6 deletions(-)
16
Makefile.objs | 2 ++
17
2 files changed, 15 insertions(+)
14
18
15
diff --git a/tests/ahci-test.c b/tests/ahci-test.c
19
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/ahci-test.c
21
--- a/qemu-storage-daemon.c
18
+++ b/tests/ahci-test.c
22
+++ b/qemu-storage-daemon.c
19
@@ -XXX,XX +XXX,XX @@ static void test_atapi_tray(void)
23
@@ -XXX,XX +XXX,XX @@
20
QDict *rsp;
24
#include "qemu/option.h"
21
25
#include "qom/object_interfaces.h"
22
fd = prepare_iso(iso_size, &tx, &iso);
26
23
- ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,format=raw "
27
+#include "sysemu/runstate.h"
24
+ ahci = ahci_boot_and_enable("-blockdev node-name=drive0,driver=file,filename=%s "
28
#include "trace/control.h"
25
"-M q35 "
29
26
- "-device ide-cd,drive=drive0 ", iso);
30
+static volatile bool exit_requested = false;
27
+ "-device ide-cd,id=cd0,drive=drive0 ", iso);
31
+
28
port = ahci_port_select(ahci);
32
+void qemu_system_killed(int signal, pid_t pid)
29
33
+{
30
ahci_atapi_eject(ahci, port);
34
+ exit_requested = true;
31
@@ -XXX,XX +XXX,XX @@ static void test_atapi_tray(void)
35
+}
32
36
+
33
/* Remove media */
37
static void help(void)
34
qmp_async("{'execute': 'blockdev-open-tray', "
38
{
35
- "'arguments': {'device': 'drive0'}}");
39
printf(
36
+ "'arguments': {'id': 'cd0'}}");
40
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
37
atapi_wait_tray(true);
41
38
rsp = qmp_receive();
42
error_init(argv[0]);
39
QDECREF(rsp);
43
qemu_init_exec_dir(argv[0]);
40
44
+ os_setup_signal_handling();
41
qmp_discard_response("{'execute': 'x-blockdev-remove-medium', "
45
42
- "'arguments': {'device': 'drive0'}}");
46
module_call_init(MODULE_INIT_QOM);
43
+ "'arguments': {'id': 'cd0'}}");
47
module_call_init(MODULE_INIT_TRACE);
44
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
45
/* Test the tray without a medium */
49
qemu_init_main_loop(&error_fatal);
46
ahci_atapi_load(ahci, port);
50
process_options(argc, argv);
47
@@ -XXX,XX +XXX,XX @@ static void test_atapi_tray(void)
51
48
"'file': { 'driver': 'file', "
52
+ while (!exit_requested) {
49
"'filename': %s }}}", iso);
53
+ main_loop_wait(false);
50
qmp_discard_response("{'execute': 'x-blockdev-insert-medium',"
54
+ }
51
- "'arguments': { 'device': 'drive0', "
55
+
52
+ "'arguments': { 'id': 'cd0', "
56
return EXIT_SUCCESS;
53
"'node-name': 'node0' }}");
57
}
54
58
diff --git a/Makefile.objs b/Makefile.objs
55
/* Again, the event shows up first */
59
index XXXXXXX..XXXXXXX 100644
56
qmp_async("{'execute': 'blockdev-close-tray', "
60
--- a/Makefile.objs
57
- "'arguments': {'device': 'drive0'}}");
61
+++ b/Makefile.objs
58
+ "'arguments': {'id': 'cd0'}}");
62
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
59
atapi_wait_tray(false);
63
60
rsp = qmp_receive();
64
storage-daemon-obj-y = block/ qom/
61
QDECREF(rsp);
65
storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o
66
+storage-daemon-obj-$(CONFIG_WIN32) += os-win32.o
67
+storage-daemon-obj-$(CONFIG_POSIX) += os-posix.o
68
69
######################################################################
70
# Target independent part of system emulation. The long term path is to
62
--
71
--
63
2.13.6
72
2.20.1
64
73
65
74
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a --chardev option to the storage daemon that works the same
2
as the -chardev option of the system emulator.
2
3
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
The syntax of the --chardev option is still considered unstable. We want
4
Message-id: 20171123020832.8165-9-mreitz@redhat.com
5
to QAPIfy it and will potentially make changes to its syntax while
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
converting it. However, we haven't decided yet on a design for the
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
QAPIfication, so QemuOpts will have to do for now.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20200224143008.13362-14-kwolf@redhat.com>
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
13
---
8
tests/qemu-iotests/103 | 2 ++
14
qemu-storage-daemon.c | 24 ++++++++++++++++++++++++
9
1 file changed, 2 insertions(+)
15
Makefile | 2 +-
16
2 files changed, 25 insertions(+), 1 deletion(-)
10
17
11
diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
18
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
12
index XXXXXXX..XXXXXXX 100755
19
index XXXXXXX..XXXXXXX 100644
13
--- a/tests/qemu-iotests/103
20
--- a/qemu-storage-daemon.c
14
+++ b/tests/qemu-iotests/103
21
+++ b/qemu-storage-daemon.c
15
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
22
@@ -XXX,XX +XXX,XX @@
16
_supported_fmt qcow2
23
17
_supported_proto file nfs
24
#include "block/block.h"
18
_supported_os Linux
25
#include "block/nbd.h"
19
+# Internal snapshots are (currently) impossible with refcount_bits=1
26
+#include "chardev/char.h"
20
+_unsupported_imgopts 'refcount_bits=1[^0-9]'
27
#include "crypto/init.h"
21
28
22
IMG_SIZE=64K
29
#include "qapi/error.h"
30
@@ -XXX,XX +XXX,XX @@ static void help(void)
31
" [,driver specific parameters...]\n"
32
" configure a block backend\n"
33
"\n"
34
+" --chardev <options> configure a character device backend\n"
35
+" (see the qemu(1) man page for possible options)\n"
36
+"\n"
37
" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
38
" [,writable=on|off][,bitmap=<name>]\n"
39
" export the specified block node over NBD\n"
40
@@ -XXX,XX +XXX,XX @@ QEMU_HELP_BOTTOM "\n",
41
42
enum {
43
OPTION_BLOCKDEV = 256,
44
+ OPTION_CHARDEV,
45
OPTION_EXPORT,
46
OPTION_NBD_SERVER,
47
OPTION_OBJECT,
48
};
49
50
+extern QemuOptsList qemu_chardev_opts;
51
+
52
static QemuOptsList qemu_object_opts = {
53
.name = "object",
54
.implied_opt_name = "qom-type",
55
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
56
57
static const struct option long_options[] = {
58
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
59
+ {"chardev", required_argument, NULL, OPTION_CHARDEV},
60
{"export", required_argument, NULL, OPTION_EXPORT},
61
{"help", no_argument, NULL, 'h'},
62
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
63
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
64
qapi_free_BlockdevOptions(options);
65
break;
66
}
67
+ case OPTION_CHARDEV:
68
+ {
69
+ /* TODO This interface is not stable until we QAPIfy it */
70
+ QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts,
71
+ optarg, true);
72
+ if (opts == NULL) {
73
+ exit(EXIT_FAILURE);
74
+ }
75
+
76
+ if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) {
77
+ /* No error, but NULL returned means help was printed */
78
+ exit(EXIT_SUCCESS);
79
+ }
80
+ qemu_opts_del(opts);
81
+ break;
82
+ }
83
case OPTION_EXPORT:
84
{
85
Visitor *v;
86
diff --git a/Makefile b/Makefile
87
index XXXXXXX..XXXXXXX 100644
88
--- a/Makefile
89
+++ b/Makefile
90
@@ -XXX,XX +XXX,XX @@ qemu-img.o: qemu-img-cmds.h
91
qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
92
qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
93
qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
94
-qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS)
95
+qemu-storage-daemon$(EXESUF): qemu-storage-daemon.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(chardev-obj-y) $(io-obj-y) $(qom-obj-y) $(storage-daemon-obj-y) $(COMMON_LDADDS)
96
97
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
23
98
24
--
99
--
25
2.13.6
100
2.20.1
26
101
27
102
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
1
Before we can add the monitor to qemu-storage-daemon, we need to add a
2
stubs for monitor_fdsets_cleanup().
2
3
3
This patch implements a test case for the scenario that was failing
4
We also need to make sure that stubs that are actually implemented in
4
prior to the patch "migration/ram.c: do not set 'postcopy_running' in
5
the monitor core aren't linked to qemu-storage-daemon so that we don't
5
POSTCOPY_INCOMING_END", commit acab30b85d.
6
get linker errors because of duplicate symbols. This is achieved by
7
moving the stubs in question to a new file stubs/monitor-core.c.
6
8
7
This new test file 201 was derived from the test file 181 authored
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
by Kevin Wolf.
10
Message-Id: <20200224143008.13362-15-kwolf@redhat.com>
9
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
10
CC: Kevin Wolf <kwolf@redhat.com>
11
CC: Max Reitz <mreitz@redhat.com>
12
CC: Cleber Rosa <crosa@redhat.com>
13
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
13
---
16
tests/qemu-iotests/201 | 120 +++++++++++++++++++++++++++++++++++++++++++++
14
stubs/monitor-core.c | 21 +++++++++++++++++++++
17
tests/qemu-iotests/201.out | 23 +++++++++
15
stubs/monitor.c | 15 ++-------------
18
tests/qemu-iotests/group | 1 +
16
stubs/Makefile.objs | 1 +
19
3 files changed, 144 insertions(+)
17
3 files changed, 24 insertions(+), 13 deletions(-)
20
create mode 100755 tests/qemu-iotests/201
18
create mode 100644 stubs/monitor-core.c
21
create mode 100644 tests/qemu-iotests/201.out
22
19
23
diff --git a/tests/qemu-iotests/201 b/tests/qemu-iotests/201
20
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
24
new file mode 100755
25
index XXXXXXX..XXXXXXX
26
--- /dev/null
27
+++ b/tests/qemu-iotests/201
28
@@ -XXX,XX +XXX,XX @@
29
+#!/bin/bash
30
+#
31
+# Test savevm and loadvm after live migration with postcopy flag
32
+#
33
+# Copyright (C) 2017, IBM Corporation.
34
+#
35
+# This file is derived from tests/qemu-iotests/181 by Kevin Wolf
36
+#
37
+# This program is free software; you can redistribute it and/or modify
38
+# it under the terms of the GNU General Public License as published by
39
+# the Free Software Foundation; either version 2 of the License, or
40
+# (at your option) any later version.
41
+#
42
+# This program is distributed in the hope that it will be useful,
43
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
44
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45
+# GNU General Public License for more details.
46
+#
47
+# You should have received a copy of the GNU General Public License
48
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
49
+
50
+seq=`basename $0`
51
+echo "QA output created by $seq"
52
+
53
+status=1    # failure is the default!
54
+
55
+MIG_SOCKET="${TEST_DIR}/migrate"
56
+
57
+# get standard environment, filters and checks
58
+. ./common.rc
59
+. ./common.filter
60
+. ./common.qemu
61
+
62
+_cleanup()
63
+{
64
+ rm -f "${MIG_SOCKET}"
65
+ _cleanup_test_img
66
+ _cleanup_qemu
67
+}
68
+trap "_cleanup; exit \$status" 0 1 2 3 15
69
+
70
+_supported_fmt qcow2
71
+_supported_proto generic
72
+_supported_os Linux
73
+
74
+# Internal snapshots are (currently) impossible with refcount_bits=1
75
+# This was taken from test 080
76
+_unsupported_imgopts 'refcount_bits=1[^0-9]'
77
+
78
+size=64M
79
+_make_test_img $size
80
+
81
+echo
82
+echo === Starting VMs ===
83
+echo
84
+
85
+qemu_comm_method="monitor"
86
+
87
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
88
+ _launch_qemu \
89
+ -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk
90
+else
91
+ _launch_qemu \
92
+ -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk
93
+fi
94
+src=$QEMU_HANDLE
95
+
96
+if [ "$IMGOPTSSYNTAX" = "true" ]; then
97
+ _launch_qemu \
98
+ -drive "${TEST_IMG}",cache=${CACHEMODE},id=disk \
99
+ -incoming "unix:${MIG_SOCKET}"
100
+else
101
+ _launch_qemu \
102
+ -drive file="${TEST_IMG}",cache=${CACHEMODE},driver=$IMGFMT,id=disk \
103
+ -incoming "unix:${MIG_SOCKET}"
104
+fi
105
+dest=$QEMU_HANDLE
106
+
107
+echo
108
+echo === Set \'migrate_set_capability postcopy-ram on\' and migrate ===
109
+echo
110
+
111
+silent=yes
112
+_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)"
113
+_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
114
+_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
115
+
116
+QEMU_COMM_TIMEOUT=1 qemu_cmd_repeat=10 silent=yes \
117
+ _send_qemu_cmd $src "info migrate" "completed\|failed"
118
+silent=yes _send_qemu_cmd $src "" "(qemu)"
119
+
120
+echo
121
+echo === Check if migration was successful ===
122
+echo
123
+
124
+QEMU_COMM_TIMEOUT=1 silent=yes \
125
+ _send_qemu_cmd $src "info migrate" "completed"
126
+silent=yes _send_qemu_cmd $src "" "(qemu)"
127
+
128
+echo
129
+echo === On destination, execute savevm and loadvm ===
130
+echo
131
+
132
+silent=
133
+_send_qemu_cmd $dest 'savevm state1' "(qemu)"
134
+_send_qemu_cmd $dest 'loadvm state1' "(qemu)"
135
+
136
+echo
137
+echo === Shut down and check image ===
138
+echo
139
+
140
+_send_qemu_cmd $src 'quit' ""
141
+_send_qemu_cmd $dest 'quit' ""
142
+wait=1 _cleanup_qemu
143
+
144
+_check_test_img
145
+
146
+# success, all done
147
+echo "*** done"
148
+status=0
149
diff --git a/tests/qemu-iotests/201.out b/tests/qemu-iotests/201.out
150
new file mode 100644
21
new file mode 100644
151
index XXXXXXX..XXXXXXX
22
index XXXXXXX..XXXXXXX
152
--- /dev/null
23
--- /dev/null
153
+++ b/tests/qemu-iotests/201.out
24
+++ b/stubs/monitor-core.c
154
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
155
+QA output created by 201
26
+#include "qemu/osdep.h"
156
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
27
+#include "monitor/monitor.h"
28
+#include "qemu-common.h"
29
+#include "qapi/qapi-emit-events.h"
157
+
30
+
158
+=== Starting VMs ===
31
+__thread Monitor *cur_mon;
32
+
33
+void monitor_init_qmp(Chardev *chr, bool pretty)
34
+{
35
+}
36
+
37
+void qapi_event_emit(QAPIEvent event, QDict *qdict)
38
+{
39
+}
40
+
41
+int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
42
+{
43
+ abort();
44
+}
159
+
45
+
160
+
46
+
161
+=== Set 'migrate_set_capability postcopy-ram on' and migrate ===
47
diff --git a/stubs/monitor.c b/stubs/monitor.c
162
+
163
+
164
+=== Check if migration was successful ===
165
+
166
+
167
+=== On destination, execute savevm and loadvm ===
168
+
169
+(qemu) savevm state1
170
+(qemu) loadvm state1
171
+
172
+=== Shut down and check image ===
173
+
174
+(qemu) quit
175
+(qemu) quit
176
+No errors were found on the image.
177
+*** done
178
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
179
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
180
--- a/tests/qemu-iotests/group
49
--- a/stubs/monitor.c
181
+++ b/tests/qemu-iotests/group
50
+++ b/stubs/monitor.c
182
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
183
197 rw auto quick
52
#include "qemu/osdep.h"
184
198 rw auto
53
#include "qapi/error.h"
185
200 rw auto
54
-#include "qapi/qapi-emit-events.h"
186
+201 rw auto migration
55
#include "monitor/monitor.h"
187
202 rw auto quick
56
-
188
203 rw auto
57
-__thread Monitor *cur_mon;
58
-
59
-int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
60
-{
61
- abort();
62
-}
63
+#include "../monitor/monitor-internal.h"
64
65
int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
66
{
67
@@ -XXX,XX +XXX,XX @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
68
return -1;
69
}
70
71
-void monitor_init_qmp(Chardev *chr, bool pretty)
72
-{
73
-}
74
-
75
void monitor_init_hmp(Chardev *chr, bool use_readline)
76
{
77
}
78
79
-void qapi_event_emit(QAPIEvent event, QDict *qdict)
80
+void monitor_fdsets_cleanup(void)
81
{
82
}
83
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
84
index XXXXXXX..XXXXXXX 100644
85
--- a/stubs/Makefile.objs
86
+++ b/stubs/Makefile.objs
87
@@ -XXX,XX +XXX,XX @@ stub-obj-y += machine-init-done.o
88
stub-obj-y += migr-blocker.o
89
stub-obj-y += change-state-handler.o
90
stub-obj-y += monitor.o
91
+stub-obj-y += monitor-core.o
92
stub-obj-y += notify-event.o
93
stub-obj-y += qtest.o
94
stub-obj-y += replay.o
189
--
95
--
190
2.13.6
96
2.20.1
191
97
192
98
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
We want to share the whitelists between the system emulator schema and
2
the storage daemon schema, so move all the pragmas from the main schema
3
file into a separate file that can be included from both.
2
4
3
In some cases, these commands still use the deprecated @device
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
parameter. Fix that so we can later drop that parameter from their
6
Message-Id: <20200224143008.13362-16-kwolf@redhat.com>
5
interface.
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
qapi/pragma.json | 24 ++++++++++++++++++++++++
11
qapi/qapi-schema.json | 25 +------------------------
12
qapi/Makefile.objs | 2 +-
13
3 files changed, 26 insertions(+), 25 deletions(-)
14
create mode 100644 qapi/pragma.json
6
15
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/qapi/pragma.json b/qapi/pragma.json
8
Message-id: 20171110224302.14424-2-mreitz@redhat.com
17
new file mode 100644
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
18
index XXXXXXX..XXXXXXX
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
--- /dev/null
11
---
20
+++ b/qapi/pragma.json
12
tests/qemu-iotests/118 | 184 +++++++++++++++++++++++--------------------------
21
@@ -XXX,XX +XXX,XX @@
13
tests/qemu-iotests/155 | 60 ++++++++--------
22
+{ 'pragma': { 'doc-required': true } }
14
2 files changed, 113 insertions(+), 131 deletions(-)
15
16
diff --git a/tests/qemu-iotests/118 b/tests/qemu-iotests/118
17
index XXXXXXX..XXXXXXX 100755
18
--- a/tests/qemu-iotests/118
19
+++ b/tests/qemu-iotests/118
20
@@ -XXX,XX +XXX,XX @@ from iotests import qemu_img
21
old_img = os.path.join(iotests.test_dir, 'test0.img')
22
new_img = os.path.join(iotests.test_dir, 'test1.img')
23
24
+def interface_to_device_name(interface):
25
+ if interface == 'ide':
26
+ return 'ide-cd'
27
+ elif interface == 'floppy':
28
+ return 'floppy'
29
+ else:
30
+ return None
31
+
23
+
32
class ChangeBaseClass(iotests.QMPTestCase):
24
+# Whitelists to permit QAPI rule violations; think twice before you
33
has_opened = False
25
+# add to them!
34
has_closed = False
26
+{ 'pragma': {
35
@@ -XXX,XX +XXX,XX @@ class ChangeBaseClass(iotests.QMPTestCase):
27
+ # Commands allowed to return a non-dictionary:
36
28
+ 'returns-whitelist': [
37
class GeneralChangeTestsBaseClass(ChangeBaseClass):
29
+ 'human-monitor-command',
38
30
+ 'qom-get',
39
- device_name = None
31
+ 'query-migrate-cache-size',
40
+ device_name = 'qdev0'
32
+ 'query-tpm-models',
41
33
+ 'query-tpm-types',
42
def test_change(self):
34
+ 'ringbuf-read' ],
43
result = self.vm.qmp('change', device='drive0', target=new_img,
35
+ 'name-case-whitelist': [
44
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
36
+ 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
45
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
37
+ 'CpuInfoMIPS', # PC, visible through query-cpu
46
38
+ 'CpuInfoTricore', # PC, visible through query-cpu
47
def test_blockdev_change_medium(self):
39
+ 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings
48
- if self.device_name is not None:
40
+ 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings
49
- result = self.vm.qmp('blockdev-change-medium',
41
+ 'QapiErrorClass', # all members, visible through errors
50
- id=self.device_name, filename=new_img,
42
+ 'UuidInfo', # UUID, visible through query-uuid
51
- format=iotests.imgfmt)
43
+ 'X86CPURegister32', # all members, visible indirectly through qom-get
52
- else:
44
+ 'CpuInfo' # CPU, visible through query-cpu
53
- result = self.vm.qmp('blockdev-change-medium',
45
+ ] } }
54
- device='drive0', filename=new_img,
46
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
55
- format=iotests.imgfmt)
47
index XXXXXXX..XXXXXXX 100644
56
+ result = self.vm.qmp('blockdev-change-medium',
48
--- a/qapi/qapi-schema.json
57
+ id=self.device_name, filename=new_img,
49
+++ b/qapi/qapi-schema.json
58
+ format=iotests.imgfmt)
50
@@ -XXX,XX +XXX,XX @@
59
51
#
60
self.assert_qmp(result, 'return', {})
52
##
61
53
62
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
54
-{ 'pragma': { 'doc-required': true } }
63
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
64
65
def test_eject(self):
66
- if self.device_name is not None:
67
- result = self.vm.qmp('eject', id=self.device_name, force=True)
68
- else:
69
- result = self.vm.qmp('eject', device='drive0', force=True)
70
+ result = self.vm.qmp('eject', id=self.device_name, force=True)
71
self.assert_qmp(result, 'return', {})
72
73
self.wait_for_open()
74
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
75
self.assert_qmp_absent(result, 'return[0]/inserted')
76
77
def test_tray_eject_change(self):
78
- if self.device_name is not None:
79
- result = self.vm.qmp('eject', id=self.device_name, force=True)
80
- else:
81
- result = self.vm.qmp('eject', device='drive0', force=True)
82
+ result = self.vm.qmp('eject', id=self.device_name, force=True)
83
self.assert_qmp(result, 'return', {})
84
85
self.wait_for_open()
86
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
87
self.assert_qmp(result, 'return[0]/tray_open', True)
88
self.assert_qmp_absent(result, 'return[0]/inserted')
89
90
- if self.device_name is not None:
91
- result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
92
- filename=new_img, format=iotests.imgfmt)
93
- else:
94
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
95
- filename=new_img, format=iotests.imgfmt)
96
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
97
+ filename=new_img, format=iotests.imgfmt)
98
self.assert_qmp(result, 'return', {})
99
100
self.wait_for_close()
101
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
102
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
103
104
def test_tray_open_close(self):
105
- if self.device_name is not None:
106
- result = self.vm.qmp('blockdev-open-tray',
107
- id=self.device_name, force=True)
108
- else:
109
- result = self.vm.qmp('blockdev-open-tray',
110
- device='drive0', force=True)
111
+ result = self.vm.qmp('blockdev-open-tray',
112
+ id=self.device_name, force=True)
113
self.assert_qmp(result, 'return', {})
114
115
self.wait_for_open()
116
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
117
else:
118
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
119
120
- if self.device_name is not None:
121
- result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
122
- else:
123
- result = self.vm.qmp('blockdev-close-tray', device='drive0')
124
+ result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
125
self.assert_qmp(result, 'return', {})
126
127
if self.has_real_tray or not self.was_empty:
128
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
129
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
130
131
def test_tray_eject_close(self):
132
- result = self.vm.qmp('eject', device='drive0', force=True)
133
+ result = self.vm.qmp('eject', id=self.device_name, force=True)
134
self.assert_qmp(result, 'return', {})
135
136
self.wait_for_open()
137
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
138
self.assert_qmp(result, 'return[0]/tray_open', True)
139
self.assert_qmp_absent(result, 'return[0]/inserted')
140
141
- if self.device_name is not None:
142
- result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
143
- else:
144
- result = self.vm.qmp('blockdev-close-tray', device='drive0')
145
+ result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
146
self.assert_qmp(result, 'return', {})
147
148
self.wait_for_close()
149
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
150
self.assert_qmp_absent(result, 'return[0]/inserted')
151
152
def test_tray_open_change(self):
153
- result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
154
+ result = self.vm.qmp('blockdev-open-tray', id=self.device_name,
155
+ force=True)
156
self.assert_qmp(result, 'return', {})
157
158
self.wait_for_open()
159
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
160
else:
161
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
162
163
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
164
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
165
filename=new_img,
166
format=iotests.imgfmt)
167
self.assert_qmp(result, 'return', {})
168
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
169
'driver': 'file'})
170
self.assert_qmp(result, 'return', {})
171
172
- if self.device_name is not None:
173
- result = self.vm.qmp('blockdev-open-tray',
174
- id=self.device_name, force=True)
175
- else:
176
- result = self.vm.qmp('blockdev-open-tray',
177
- device='drive0', force=True)
178
+ result = self.vm.qmp('blockdev-open-tray',
179
+ id=self.device_name, force=True)
180
self.assert_qmp(result, 'return', {})
181
182
self.wait_for_open()
183
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
184
else:
185
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
186
187
- if self.device_name is not None:
188
- result = self.vm.qmp('x-blockdev-remove-medium',
189
- id=self.device_name)
190
- else:
191
- result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
192
+ result = self.vm.qmp('x-blockdev-remove-medium',
193
+ id=self.device_name)
194
self.assert_qmp(result, 'return', {})
195
196
result = self.vm.qmp('query-block')
197
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
198
self.assert_qmp(result, 'return[0]/tray_open', True)
199
self.assert_qmp_absent(result, 'return[0]/inserted')
200
201
- if self.device_name is not None:
202
- result = self.vm.qmp('x-blockdev-insert-medium',
203
- id=self.device_name, node_name='new')
204
- else:
205
- result = self.vm.qmp('x-blockdev-insert-medium',
206
- device='drive0', node_name='new')
207
+ result = self.vm.qmp('x-blockdev-insert-medium',
208
+ id=self.device_name, node_name='new')
209
self.assert_qmp(result, 'return', {})
210
211
result = self.vm.qmp('query-block')
212
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
213
self.assert_qmp(result, 'return[0]/tray_open', True)
214
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
215
216
- if self.device_name is not None:
217
- result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
218
- else:
219
- result = self.vm.qmp('blockdev-close-tray', device='drive0')
220
+ result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
221
self.assert_qmp(result, 'return', {})
222
223
self.wait_for_close()
224
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
225
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
226
227
def test_close_on_closed(self):
228
- result = self.vm.qmp('blockdev-close-tray', device='drive0')
229
+ result = self.vm.qmp('blockdev-close-tray', id=self.device_name)
230
# Should be a no-op
231
self.assert_qmp(result, 'return', {})
232
self.assertEquals(self.vm.get_qmp_events(wait=False), [])
233
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
234
if not self.has_real_tray:
235
return
236
237
- result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
238
+ result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
239
self.assert_qmp(result, 'error/class', 'GenericError')
240
241
def test_insert_on_closed(self):
242
@@ -XXX,XX +XXX,XX @@ class GeneralChangeTestsBaseClass(ChangeBaseClass):
243
'driver': 'file'})
244
self.assert_qmp(result, 'return', {})
245
246
- result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
247
+ result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
248
node_name='new')
249
self.assert_qmp(result, 'error/class', 'GenericError')
250
251
@@ -XXX,XX +XXX,XX @@ class TestInitiallyFilled(GeneralChangeTestsBaseClass):
252
qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
253
qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
254
self.vm = iotests.VM()
255
- if interface == 'ide':
256
- self.device_name = 'qdev0'
257
- self.vm.add_drive(old_img, 'media=%s' % media, 'none')
258
- self.vm.add_device('ide-cd,drive=drive0,id=%s' % self.device_name)
259
- else:
260
- self.vm.add_drive(old_img, 'media=%s' % media, interface)
261
+ self.vm.add_drive(old_img, 'media=%s' % media, 'none')
262
+ self.vm.add_device('%s,drive=drive0,id=%s' %
263
+ (interface_to_device_name(interface),
264
+ self.device_name))
265
self.vm.launch()
266
267
def tearDown(self):
268
@@ -XXX,XX +XXX,XX @@ class TestInitiallyFilled(GeneralChangeTestsBaseClass):
269
'driver': 'file'})
270
self.assert_qmp(result, 'return', {})
271
272
- result = self.vm.qmp('blockdev-open-tray', device='drive0')
273
+ result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
274
self.assert_qmp(result, 'return', {})
275
276
self.wait_for_open()
277
278
- result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
279
+ result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
280
node_name='new')
281
self.assert_qmp(result, 'error/class', 'GenericError')
282
283
@@ -XXX,XX +XXX,XX @@ class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
284
285
def setUp(self, media, interface):
286
qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
287
- self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
288
+ self.vm = iotests.VM().add_drive(None, 'media=%s' % media, 'none')
289
+ self.vm.add_device('%s,drive=drive0,id=%s' %
290
+ (interface_to_device_name(interface),
291
+ self.device_name))
292
self.vm.launch()
293
294
def tearDown(self):
295
@@ -XXX,XX +XXX,XX @@ class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
296
os.remove(new_img)
297
298
def test_remove_on_empty(self):
299
- result = self.vm.qmp('blockdev-open-tray', device='drive0')
300
+ result = self.vm.qmp('blockdev-open-tray', id=self.device_name)
301
self.assert_qmp(result, 'return', {})
302
303
self.wait_for_open()
304
305
- result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
306
+ result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
307
# Should be a no-op
308
self.assert_qmp(result, 'return', {})
309
310
@@ -XXX,XX +XXX,XX @@ class TestFloppyInitiallyEmpty(TestInitiallyEmpty):
311
self.has_opened = True
312
313
class TestChangeReadOnly(ChangeBaseClass):
314
+ device_name = 'qdev0'
315
+
316
def setUp(self):
317
qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
318
qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
319
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
320
def test_ro_ro_retain(self):
321
os.chmod(old_img, 0444)
322
os.chmod(new_img, 0444)
323
- self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
324
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
325
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
326
self.vm.launch()
327
328
result = self.vm.qmp('query-block')
329
self.assert_qmp(result, 'return[0]/inserted/ro', True)
330
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
331
332
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
333
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
334
filename=new_img,
335
format=iotests.imgfmt,
336
read_only_mode='retain')
337
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
338
339
def test_ro_rw_retain(self):
340
os.chmod(old_img, 0444)
341
- self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
342
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
343
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
344
self.vm.launch()
345
346
result = self.vm.qmp('query-block')
347
self.assert_qmp(result, 'return[0]/inserted/ro', True)
348
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
349
350
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
351
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
352
filename=new_img,
353
format=iotests.imgfmt,
354
read_only_mode='retain')
355
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
356
357
def test_rw_ro_retain(self):
358
os.chmod(new_img, 0444)
359
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
360
+ self.vm.add_drive(old_img, 'media=disk', 'none')
361
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
362
self.vm.launch()
363
364
result = self.vm.qmp('query-block')
365
self.assert_qmp(result, 'return[0]/inserted/ro', False)
366
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
367
368
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
369
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
370
filename=new_img,
371
format=iotests.imgfmt,
372
read_only_mode='retain')
373
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
374
375
def test_ro_rw(self):
376
os.chmod(old_img, 0444)
377
- self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
378
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
379
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
380
self.vm.launch()
381
382
result = self.vm.qmp('query-block')
383
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
384
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
385
386
result = self.vm.qmp('blockdev-change-medium',
387
- device='drive0',
388
+ id=self.device_name,
389
filename=new_img,
390
format=iotests.imgfmt,
391
read_only_mode='read-write')
392
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
393
394
def test_rw_ro(self):
395
os.chmod(new_img, 0444)
396
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
397
+ self.vm.add_drive(old_img, 'media=disk', 'none')
398
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
399
self.vm.launch()
400
401
result = self.vm.qmp('query-block')
402
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
403
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
404
405
result = self.vm.qmp('blockdev-change-medium',
406
- device='drive0',
407
+ id=self.device_name,
408
filename=new_img,
409
format=iotests.imgfmt,
410
read_only_mode='read-only')
411
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
412
self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
413
414
def test_make_rw_ro(self):
415
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
416
+ self.vm.add_drive(old_img, 'media=disk', 'none')
417
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
418
self.vm.launch()
419
420
result = self.vm.qmp('query-block')
421
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
422
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
423
424
result = self.vm.qmp('blockdev-change-medium',
425
- device='drive0',
426
+ id=self.device_name,
427
filename=new_img,
428
format=iotests.imgfmt,
429
read_only_mode='read-only')
430
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
431
432
def test_make_ro_rw(self):
433
os.chmod(new_img, 0444)
434
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
435
+ self.vm.add_drive(old_img, 'media=disk', 'none')
436
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
437
self.vm.launch()
438
439
result = self.vm.qmp('query-block')
440
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
441
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
442
443
result = self.vm.qmp('blockdev-change-medium',
444
- device='drive0',
445
+ id=self.device_name,
446
filename=new_img,
447
format=iotests.imgfmt,
448
read_only_mode='read-write')
449
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
450
451
def test_make_rw_ro_by_retain(self):
452
os.chmod(old_img, 0444)
453
- self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
454
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'none')
455
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
456
self.vm.launch()
457
458
result = self.vm.qmp('query-block')
459
self.assert_qmp(result, 'return[0]/inserted/ro', True)
460
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
461
462
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
463
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
464
filename=new_img,
465
format=iotests.imgfmt,
466
read_only_mode='retain')
467
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
468
469
def test_make_ro_rw_by_retain(self):
470
os.chmod(new_img, 0444)
471
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
472
+ self.vm.add_drive(old_img, 'media=disk', 'none')
473
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
474
self.vm.launch()
475
476
result = self.vm.qmp('query-block')
477
self.assert_qmp(result, 'return[0]/inserted/ro', False)
478
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
479
480
- result = self.vm.qmp('blockdev-change-medium', device='drive0',
481
+ result = self.vm.qmp('blockdev-change-medium', id=self.device_name,
482
filename=new_img,
483
format=iotests.imgfmt,
484
read_only_mode='retain')
485
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
486
487
def test_rw_ro_cycle(self):
488
os.chmod(new_img, 0444)
489
- self.vm.add_drive(old_img, 'media=disk', 'floppy')
490
+ self.vm.add_drive(old_img, 'media=disk', 'none')
491
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
492
self.vm.launch()
493
494
result = self.vm.qmp('query-block')
495
@@ -XXX,XX +XXX,XX @@ class TestChangeReadOnly(ChangeBaseClass):
496
self.assert_qmp(result, 'return[0]/inserted/ro', False)
497
self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
498
499
- result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
500
+ result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
501
self.assert_qmp(result, 'return', {})
502
503
result = self.vm.qmp('query-block')
504
self.assert_qmp_absent(result, 'return[0]/inserted')
505
506
- result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
507
+ result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
508
node_name='new')
509
self.assert_qmp(result, 'return', {})
510
511
@@ -XXX,XX +XXX,XX @@ TestInitiallyEmpty = None
512
513
514
class TestBlockJobsAfterCycle(ChangeBaseClass):
515
+ device_name = 'qdev0'
516
+
517
def setUp(self):
518
- qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
519
+ qemu_img('create', '-f', iotests.imgfmt, old_img, '1440K')
520
521
self.vm = iotests.VM()
522
self.vm.add_drive_raw("id=drive0,driver=null-co,if=none")
523
+ self.vm.add_device('floppy,drive=drive0,id=%s' % self.device_name)
524
self.vm.launch()
525
526
result = self.vm.qmp('query-block')
527
@@ -XXX,XX +XXX,XX @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
528
529
# For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
530
# is not necessary
531
- result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
532
+ result = self.vm.qmp('x-blockdev-remove-medium', id=self.device_name)
533
self.assert_qmp(result, 'return', {})
534
535
result = self.vm.qmp('query-block')
536
@@ -XXX,XX +XXX,XX @@ class TestBlockJobsAfterCycle(ChangeBaseClass):
537
'driver': 'file'})
538
self.assert_qmp(result, 'return', {})
539
540
- result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
541
+ result = self.vm.qmp('x-blockdev-insert-medium', id=self.device_name,
542
node_name='node0')
543
self.assert_qmp(result, 'return', {})
544
545
diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155
546
index XXXXXXX..XXXXXXX 100755
547
--- a/tests/qemu-iotests/155
548
+++ b/tests/qemu-iotests/155
549
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
550
target_real_backing = None
551
552
def setUp(self):
553
- qemu_img('create', '-f', iotests.imgfmt, back0_img, '1M')
554
+ qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K')
555
qemu_img('create', '-f', iotests.imgfmt, '-b', back0_img, back1_img)
556
qemu_img('create', '-f', iotests.imgfmt, '-b', back1_img, back2_img)
557
qemu_img('create', '-f', iotests.imgfmt, '-b', back2_img, source_img)
558
559
self.vm = iotests.VM()
560
- self.vm.add_drive(None, '', 'none')
561
- self.vm.launch()
562
-
55
-
563
# Add the BDS via blockdev-add so it stays around after the mirror block
56
-# Whitelists to permit QAPI rule violations; think twice before you
564
# job has been completed
57
-# add to them!
565
- result = self.vm.qmp('blockdev-add',
58
-{ 'pragma': {
566
- node_name='source',
59
- # Commands allowed to return a non-dictionary:
567
- driver=iotests.imgfmt,
60
- 'returns-whitelist': [
568
- file={'driver': 'file',
61
- 'human-monitor-command',
569
- 'filename': source_img})
62
- 'qom-get',
570
- self.assert_qmp(result, 'return', {})
63
- 'query-migrate-cache-size',
571
-
64
- 'query-tpm-models',
572
- result = self.vm.qmp('x-blockdev-insert-medium',
65
- 'query-tpm-types',
573
- device='drive0', node_name='source')
66
- 'ringbuf-read' ],
574
- self.assert_qmp(result, 'return', {})
67
- 'name-case-whitelist': [
575
+ blockdev = {'node-name': 'source',
68
- 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
576
+ 'driver': iotests.imgfmt,
69
- 'CpuInfoMIPS', # PC, visible through query-cpu
577
+ 'file': {'driver': 'file',
70
- 'CpuInfoTricore', # PC, visible through query-cpu
578
+ 'filename': source_img}}
71
- 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings
579
+ self.vm.add_blockdev(self.qmp_to_opts(blockdev))
72
- 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings
580
+ self.vm.add_device('floppy,id=qdev0,drive=source')
73
- 'QapiErrorClass', # all members, visible through errors
581
+ self.vm.launch()
74
- 'UuidInfo', # UUID, visible through query-uuid
582
75
- 'X86CPURegister32', # all members, visible indirectly through qom-get
583
self.assertIntactSourceBackingChain()
76
- 'CpuInfo' # CPU, visible through query-cpu
584
77
- ] } }
585
if self.existing:
78
+{ 'include': 'pragma.json' }
586
if self.target_backing:
79
587
qemu_img('create', '-f', iotests.imgfmt,
80
# Documentation generated with qapi-gen.py is in source order, with
588
- '-b', self.target_backing, target_img, '1M')
81
# included sub-schemas inserted at the first include directive
589
+ '-b', self.target_backing, target_img, '1440K')
82
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
590
else:
83
index XXXXXXX..XXXXXXX 100644
591
- qemu_img('create', '-f', iotests.imgfmt, target_img, '1M')
84
--- a/qapi/Makefile.objs
592
+ qemu_img('create', '-f', iotests.imgfmt, target_img, '1440K')
85
+++ b/qapi/Makefile.objs
593
86
@@ -XXX,XX +XXX,XX @@ util-obj-y += qapi-util.o
594
if self.cmd == 'blockdev-mirror':
87
595
options = { 'node-name': 'target',
88
QAPI_COMMON_MODULES = audio authz block-core block char common control crypto
596
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
89
QAPI_COMMON_MODULES += dump error introspect job machine migration misc
597
except OSError:
90
-QAPI_COMMON_MODULES += net qdev qom rdma rocker run-state sockets tpm
598
pass
91
+QAPI_COMMON_MODULES += net pragma qdev qom rdma rocker run-state sockets tpm
599
92
QAPI_COMMON_MODULES += trace transaction ui
600
- def findBlockNode(self, node_name, id=None):
93
QAPI_TARGET_MODULES = machine-target misc-target
601
- if id:
94
QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES)
602
+ def findBlockNode(self, node_name, qdev=None):
603
+ if qdev:
604
result = self.vm.qmp('query-block')
605
for device in result['return']:
606
- if device['device'] == id:
607
+ if device['qdev'] == qdev:
608
if node_name:
609
self.assert_qmp(device, 'inserted/node-name', node_name)
610
return device['inserted']
611
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
612
if node['node-name'] == node_name:
613
return node
614
615
- self.fail('Cannot find node %s/%s' % (id, node_name))
616
+ self.fail('Cannot find node %s/%s' % (qdev, node_name))
617
618
def assertIntactSourceBackingChain(self):
619
node = self.findBlockNode('source')
620
@@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase):
621
class MirrorBaseClass(BaseClass):
622
def runMirror(self, sync):
623
if self.cmd == 'blockdev-mirror':
624
- result = self.vm.qmp(self.cmd, device='drive0', sync=sync,
625
- target='target')
626
+ result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source',
627
+ sync=sync, target='target')
628
else:
629
if self.existing:
630
mode = 'existing'
631
else:
632
mode = 'absolute-paths'
633
- result = self.vm.qmp(self.cmd, device='drive0', sync=sync,
634
- target=target_img, format=iotests.imgfmt,
635
- mode=mode, node_name='target')
636
+ result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source',
637
+ sync=sync, target=target_img,
638
+ format=iotests.imgfmt, mode=mode,
639
+ node_name='target')
640
641
self.assert_qmp(result, 'return', {})
642
643
self.vm.event_wait('BLOCK_JOB_READY')
644
645
- result = self.vm.qmp('block-job-complete', device='drive0')
646
+ result = self.vm.qmp('block-job-complete', device='mirror-job')
647
self.assert_qmp(result, 'return', {})
648
649
self.vm.event_wait('BLOCK_JOB_COMPLETED')
650
@@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass):
651
def testFull(self):
652
self.runMirror('full')
653
654
- node = self.findBlockNode('target', 'drive0')
655
+ node = self.findBlockNode('target', 'qdev0')
656
self.assertCorrectBackingImage(node, None)
657
self.assertIntactSourceBackingChain()
658
659
def testTop(self):
660
self.runMirror('top')
661
662
- node = self.findBlockNode('target', 'drive0')
663
+ node = self.findBlockNode('target', 'qdev0')
664
self.assertCorrectBackingImage(node, back2_img)
665
self.assertIntactSourceBackingChain()
666
667
def testNone(self):
668
self.runMirror('none')
669
670
- node = self.findBlockNode('target', 'drive0')
671
+ node = self.findBlockNode('target', 'qdev0')
672
self.assertCorrectBackingImage(node, source_img)
673
self.assertIntactSourceBackingChain()
674
675
@@ -XXX,XX +XXX,XX @@ class TestCommit(BaseClass):
676
existing = False
677
678
def testCommit(self):
679
- result = self.vm.qmp('block-commit', device='drive0', base=back1_img)
680
+ result = self.vm.qmp('block-commit', job_id='commit-job',
681
+ device='source', base=back1_img)
682
self.assert_qmp(result, 'return', {})
683
684
self.vm.event_wait('BLOCK_JOB_READY')
685
686
- result = self.vm.qmp('block-job-complete', device='drive0')
687
+ result = self.vm.qmp('block-job-complete', device='commit-job')
688
self.assert_qmp(result, 'return', {})
689
690
self.vm.event_wait('BLOCK_JOB_COMPLETED')
691
692
- node = self.findBlockNode(None, 'drive0')
693
+ node = self.findBlockNode(None, 'qdev0')
694
self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename',
695
back1_img)
696
self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename',
697
--
95
--
698
2.13.6
96
2.20.1
699
97
700
98
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This adds a new QAPI-based monitor_init() function. The existing
2
monitor_init_opts() is rewritten to simply put its QemuOpts parameter
3
into a visitor and pass the resulting QAPI object to monitor_init().
2
4
3
This is certainly not complete, but it includes at least write_aio and
5
This will cause some change in those error messages for the monitor
4
read_aio.
6
options in the system emulator that are now generated by the visitor
7
rather than explicitly checked in monitor_init_opts().
5
8
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-id: 20171123020832.8165-5-mreitz@redhat.com
10
Message-Id: <20200224143008.13362-17-kwolf@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
block/vmdk.c | 16 ++++++++++++++++
14
qapi/control.json | 36 ++++++++++++++++++
12
1 file changed, 16 insertions(+)
15
include/monitor/monitor.h | 2 +
16
monitor/monitor.c | 77 +++++++++++++++++++++------------------
17
3 files changed, 80 insertions(+), 35 deletions(-)
13
18
14
diff --git a/block/vmdk.c b/block/vmdk.c
19
diff --git a/qapi/control.json b/qapi/control.json
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/block/vmdk.c
21
--- a/qapi/control.json
17
+++ b/block/vmdk.c
22
+++ b/qapi/control.json
18
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
23
@@ -XXX,XX +XXX,XX @@
19
/* Read backing data before skip range */
24
# <- { "return": {} }
20
if (skip_start_bytes > 0) {
25
##
21
if (bs->backing) {
26
{ 'command': 'quit' }
22
+ /* qcow2 emits this on bs->file instead of bs->backing */
27
+
23
+ BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
28
+##
24
ret = bdrv_pread(bs->backing, offset, whole_grain,
29
+# @MonitorMode:
25
skip_start_bytes);
30
+#
26
if (ret < 0) {
31
+# An enumeration of monitor modes.
27
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
32
+#
28
goto exit;
33
+# @readline: HMP monitor (human-oriented command line interface)
29
}
34
+#
30
}
35
+# @control: QMP monitor (JSON-based machine interface)
31
+ BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
36
+#
32
ret = bdrv_pwrite(extent->file, cluster_offset, whole_grain,
37
+# Since: 5.0
33
skip_start_bytes);
38
+##
34
if (ret < 0) {
39
+{ 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] }
35
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
40
+
36
/* Read backing data after skip range */
41
+##
37
if (skip_end_bytes < cluster_bytes) {
42
+# @MonitorOptions:
38
if (bs->backing) {
43
+#
39
+ /* qcow2 emits this on bs->file instead of bs->backing */
44
+# Options to be used for adding a new monitor.
40
+ BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
45
+#
41
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
46
+# @id: Name of the monitor
42
whole_grain + skip_end_bytes,
47
+#
43
cluster_bytes - skip_end_bytes);
48
+# @mode: Selects the monitor mode (default: readline)
44
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
49
+#
45
goto exit;
50
+# @pretty: Enables pretty printing (QMP only)
46
}
51
+#
47
}
52
+# @chardev: Name of a character device to expose the monitor on
48
+ BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
53
+#
49
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
54
+# Since: 5.0
50
whole_grain + skip_end_bytes,
55
+##
51
cluster_bytes - skip_end_bytes);
56
+{ 'struct': 'MonitorOptions',
52
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
57
+ 'data': {
58
+ '*id': 'str',
59
+ '*mode': 'MonitorMode',
60
+ '*pretty': 'bool',
61
+ 'chardev': 'str'
62
+ } }
63
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/include/monitor/monitor.h
66
+++ b/include/monitor/monitor.h
67
@@ -XXX,XX +XXX,XX @@
68
69
extern __thread Monitor *cur_mon;
70
typedef struct MonitorHMP MonitorHMP;
71
+typedef struct MonitorOptions MonitorOptions;
72
73
#define QMP_REQ_QUEUE_LEN_MAX 8
74
75
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals(void);
76
void monitor_init_globals_core(void);
77
void monitor_init_qmp(Chardev *chr, bool pretty);
78
void monitor_init_hmp(Chardev *chr, bool use_readline);
79
+int monitor_init(MonitorOptions *opts, Error **errp);
80
int monitor_init_opts(QemuOpts *opts, Error **errp);
81
void monitor_cleanup(void);
82
83
diff --git a/monitor/monitor.c b/monitor/monitor.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/monitor/monitor.c
86
+++ b/monitor/monitor.c
87
@@ -XXX,XX +XXX,XX @@
88
#include "qemu/osdep.h"
89
#include "monitor-internal.h"
90
#include "qapi/error.h"
91
+#include "qapi/opts-visitor.h"
92
#include "qapi/qapi-emit-events.h"
93
+#include "qapi/qapi-visit-control.h"
94
#include "qapi/qmp/qdict.h"
95
#include "qapi/qmp/qstring.h"
96
#include "qemu/error-report.h"
97
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals_core(void)
98
NULL);
99
}
100
101
-int monitor_init_opts(QemuOpts *opts, Error **errp)
102
+int monitor_init(MonitorOptions *opts, Error **errp)
53
{
103
{
54
offset = cpu_to_le32(offset);
104
Chardev *chr;
55
/* update L2 table */
105
- bool qmp;
56
+ BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
106
- bool pretty = false;
57
if (bdrv_pwrite_sync(extent->file,
107
- const char *chardev;
58
((int64_t)m_data->l2_offset * 512)
108
- const char *mode;
59
+ (m_data->l2_index * sizeof(offset)),
109
-
60
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
110
- mode = qemu_opt_get(opts, "mode");
61
}
111
- if (mode == NULL) {
112
- mode = "readline";
113
- }
114
- if (strcmp(mode, "readline") == 0) {
115
- qmp = false;
116
- } else if (strcmp(mode, "control") == 0) {
117
- qmp = true;
118
- } else {
119
- error_setg(errp, "unknown monitor mode \"%s\"", mode);
120
+
121
+ chr = qemu_chr_find(opts->chardev);
122
+ if (chr == NULL) {
123
+ error_setg(errp, "chardev \"%s\" not found", opts->chardev);
124
return -1;
62
}
125
}
63
l2_table = extent->l2_cache + (min_index * extent->l2_size);
126
64
+ BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
127
- if (!qmp && qemu_opt_get(opts, "pretty")) {
65
if (bdrv_pread(extent->file,
128
- warn_report("'pretty' is deprecated for HMP monitors, it has no effect "
66
(int64_t)l2_offset * 512,
129
- "and will be removed in future versions");
67
l2_table,
130
- }
68
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
131
- if (qemu_opt_get_bool(opts, "pretty", 0)) {
69
.iov_len = n_bytes,
132
- pretty = true;
70
};
133
+ switch (opts->mode) {
71
qemu_iovec_init_external(&local_qiov, &iov, 1);
134
+ case MONITOR_MODE_CONTROL:
135
+ monitor_init_qmp(chr, opts->pretty);
136
+ break;
137
+ case MONITOR_MODE_READLINE:
138
+ if (opts->pretty) {
139
+ warn_report("'pretty' is deprecated for HMP monitors, it has no "
140
+ "effect and will be removed in future versions");
141
+ }
142
+ monitor_init_hmp(chr, true);
143
+ break;
144
+ default:
145
+ g_assert_not_reached();
146
}
147
148
- chardev = qemu_opt_get(opts, "chardev");
149
- if (!chardev) {
150
- error_report("chardev is required");
151
- exit(1);
152
- }
153
- chr = qemu_chr_find(chardev);
154
- if (chr == NULL) {
155
- error_setg(errp, "chardev \"%s\" not found", chardev);
156
- return -1;
157
+ return 0;
158
+}
72
+
159
+
73
+ BLKDBG_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED);
160
+int monitor_init_opts(QemuOpts *opts, Error **errp)
74
} else {
161
+{
75
qemu_iovec_init(&local_qiov, qiov->niov);
162
+ Visitor *v;
76
qemu_iovec_concat(&local_qiov, qiov, qiov_offset, n_bytes);
163
+ MonitorOptions *options;
164
+ Error *local_err = NULL;
77
+
165
+
78
+ BLKDBG_EVENT(extent->file, BLKDBG_WRITE_AIO);
166
+ v = opts_visitor_new(opts);
167
+ visit_type_MonitorOptions(v, NULL, &options, &local_err);
168
+ visit_free(v);
169
+
170
+ if (local_err) {
171
+ goto out;
79
}
172
}
80
173
81
write_offset = cluster_offset + offset_in_cluster;
174
- if (qmp) {
82
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
175
- monitor_init_qmp(chr, pretty);
83
176
- } else {
84
177
- monitor_init_hmp(chr, true);
85
if (!extent->compressed) {
178
+ monitor_init(options, &local_err);
86
+ BLKDBG_EVENT(extent->file, BLKDBG_READ_AIO);
179
+ qapi_free_MonitorOptions(options);
87
ret = bdrv_co_preadv(extent->file,
180
+
88
cluster_offset + offset_in_cluster, bytes,
181
+out:
89
qiov, 0);
182
+ if (local_err) {
90
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
183
+ error_propagate(errp, local_err);
91
buf_bytes = cluster_bytes * 2;
184
+ return -1;
92
cluster_buf = g_malloc(buf_bytes);
185
}
93
uncomp_buf = g_malloc(cluster_bytes);
186
return 0;
94
+ BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
187
}
95
ret = bdrv_pread(extent->file,
96
cluster_offset,
97
cluster_buf, buf_bytes);
98
@@ -XXX,XX +XXX,XX @@ vmdk_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
99
qemu_iovec_reset(&local_qiov);
100
qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes);
101
102
+ /* qcow2 emits this on bs->file instead of bs->backing */
103
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
104
ret = bdrv_co_preadv(bs->backing, offset, n_bytes,
105
&local_qiov, 0);
106
if (ret < 0) {
107
--
188
--
108
2.13.6
189
2.20.1
109
190
110
191
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Trying to attach a QMP monitor to a chardev that is already in use
2
results in a crash because monitor_init_qmp() passes &error_abort to
3
qemu_chr_fe_init():
2
4
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
5
$ ./x86_64-softmmu/qemu-system-x86_64 --chardev stdio,id=foo --mon foo,mode=control --mon foo,mode=control
4
Message-id: 20171123020832.8165-2-mreitz@redhat.com
6
Unexpected error in qemu_chr_fe_init() at chardev/char-fe.c:220:
5
Reviewed-by: Eric Blake <eblake@redhat.com>
7
qemu-system-x86_64: --mon foo,mode=control: Device 'foo' is in use
6
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Abgebrochen (Speicherabzug geschrieben)
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
10
Fix this by allowing monitor_init_qmp() to return an error and passing
11
any error in qemu_chr_fe_init() to its caller instead of aborting.
12
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20200224143008.13362-18-kwolf@redhat.com>
15
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
17
---
9
block/vmdk.c | 2 +-
18
include/monitor/monitor.h | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
19
monitor/monitor.c | 7 ++++++-
20
monitor/qmp.c | 11 +++++++----
21
stubs/monitor-core.c | 2 +-
22
tests/test-util-sockets.c | 2 +-
23
5 files changed, 16 insertions(+), 8 deletions(-)
11
24
12
diff --git a/block/vmdk.c b/block/vmdk.c
25
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
13
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vmdk.c
27
--- a/include/monitor/monitor.h
15
+++ b/block/vmdk.c
28
+++ b/include/monitor/monitor.h
16
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset,
29
@@ -XXX,XX +XXX,XX @@ bool monitor_cur_is_qmp(void);
17
qemu_iovec_concat(&local_qiov, qiov, qiov_offset, n_bytes);
30
31
void monitor_init_globals(void);
32
void monitor_init_globals_core(void);
33
-void monitor_init_qmp(Chardev *chr, bool pretty);
34
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
35
void monitor_init_hmp(Chardev *chr, bool use_readline);
36
int monitor_init(MonitorOptions *opts, Error **errp);
37
int monitor_init_opts(QemuOpts *opts, Error **errp);
38
diff --git a/monitor/monitor.c b/monitor/monitor.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/monitor/monitor.c
41
+++ b/monitor/monitor.c
42
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals_core(void)
43
int monitor_init(MonitorOptions *opts, Error **errp)
44
{
45
Chardev *chr;
46
+ Error *local_err = NULL;
47
48
chr = qemu_chr_find(opts->chardev);
49
if (chr == NULL) {
50
@@ -XXX,XX +XXX,XX @@ int monitor_init(MonitorOptions *opts, Error **errp)
51
52
switch (opts->mode) {
53
case MONITOR_MODE_CONTROL:
54
- monitor_init_qmp(chr, opts->pretty);
55
+ monitor_init_qmp(chr, opts->pretty, &local_err);
56
break;
57
case MONITOR_MODE_READLINE:
58
if (opts->pretty) {
59
@@ -XXX,XX +XXX,XX @@ int monitor_init(MonitorOptions *opts, Error **errp)
60
g_assert_not_reached();
18
}
61
}
19
62
20
- write_offset = cluster_offset + offset_in_cluster,
63
+ if (local_err) {
21
+ write_offset = cluster_offset + offset_in_cluster;
64
+ error_propagate(errp, local_err);
22
ret = bdrv_co_pwritev(extent->file, write_offset, n_bytes,
65
+ return -1;
23
&local_qiov, 0);
66
+ }
67
return 0;
68
}
69
70
diff --git a/monitor/qmp.c b/monitor/qmp.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/monitor/qmp.c
73
+++ b/monitor/qmp.c
74
@@ -XXX,XX +XXX,XX @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
75
monitor_list_append(&mon->common);
76
}
77
78
-void monitor_init_qmp(Chardev *chr, bool pretty)
79
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
80
{
81
MonitorQMP *mon = g_new0(MonitorQMP, 1);
82
83
+ if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) {
84
+ g_free(mon);
85
+ return;
86
+ }
87
+ qemu_chr_fe_set_echo(&mon->common.chr, true);
88
+
89
/* Note: we run QMP monitor in I/O thread when @chr supports that */
90
monitor_data_init(&mon->common, true, false,
91
qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT));
92
@@ -XXX,XX +XXX,XX @@ void monitor_init_qmp(Chardev *chr, bool pretty)
93
qemu_mutex_init(&mon->qmp_queue_lock);
94
mon->qmp_requests = g_queue_new();
95
96
- qemu_chr_fe_init(&mon->common.chr, chr, &error_abort);
97
- qemu_chr_fe_set_echo(&mon->common.chr, true);
98
-
99
json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL);
100
if (mon->common.use_io_thread) {
101
/*
102
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/stubs/monitor-core.c
105
+++ b/stubs/monitor-core.c
106
@@ -XXX,XX +XXX,XX @@
107
108
__thread Monitor *cur_mon;
109
110
-void monitor_init_qmp(Chardev *chr, bool pretty)
111
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
112
{
113
}
114
115
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/test-util-sockets.c
118
+++ b/tests/test-util-sockets.c
119
@@ -XXX,XX +XXX,XX @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
120
*/
121
__thread Monitor *cur_mon;
122
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
123
-void monitor_init_qmp(Chardev *chr, bool pretty) {}
124
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {}
125
void monitor_init_hmp(Chardev *chr, bool use_readline) {}
126
24
127
25
--
128
--
26
2.13.6
129
2.20.1
27
130
28
131
diff view generated by jsdifflib
1
From: Hikaru Nishida <hikarupsp@gmail.com>
1
Trying to attach a HMP monitor to a chardev that is already in use
2
results in a crash because monitor_init_hmp() passes &error_abort to
3
qemu_chr_fe_init():
2
4
3
Pin-based interrupt of NVMe controller did not work properly
5
$ ./x86_64-softmmu/qemu-system-x86_64 --chardev stdio,id=foo --mon foo --mon foo
4
because using an obsolated function pci_irq_pulse().
6
QEMU 4.2.50 monitor - type 'help' for more information
5
To fix this, change to use pci_irq_assert() / pci_irq_deassert()
7
(qemu) Unexpected error in qemu_chr_fe_init() at chardev/char-fe.c:220:
6
instead of pci_irq_pulse().
8
qemu-system-x86_64: --mon foo: Device 'foo' is in use
9
Abgebrochen (Speicherabzug geschrieben)
7
10
8
Signed-off-by: Hikaru Nishida <hikarupsp@gmail.com>
11
Fix this by allowing monitor_init_hmp() to return an error and passing
9
Reviewed-by: Keith Busch <keith.busch@intel.com>
12
any error in qemu_chr_fe_init() to its caller instead of aborting.
13
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Message-Id: <20200224143008.13362-19-kwolf@redhat.com>
16
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
18
---
12
hw/block/nvme.h | 1 +
19
include/monitor/monitor.h | 2 +-
13
hw/block/nvme.c | 39 ++++++++++++++++++++++++++++++++++-----
20
chardev/char.c | 8 +++++++-
14
2 files changed, 35 insertions(+), 5 deletions(-)
21
gdbstub.c | 2 +-
22
monitor/hmp.c | 8 ++++++--
23
monitor/monitor.c | 2 +-
24
stubs/monitor.c | 2 +-
25
tests/test-util-sockets.c | 2 +-
26
7 files changed, 18 insertions(+), 8 deletions(-)
15
27
16
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
28
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
17
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/block/nvme.h
30
--- a/include/monitor/monitor.h
19
+++ b/hw/block/nvme.h
31
+++ b/include/monitor/monitor.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
32
@@ -XXX,XX +XXX,XX @@ bool monitor_cur_is_qmp(void);
21
uint32_t cmbsz;
33
void monitor_init_globals(void);
22
uint32_t cmbloc;
34
void monitor_init_globals_core(void);
23
uint8_t *cmbuf;
35
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
24
+ uint64_t irq_status;
36
-void monitor_init_hmp(Chardev *chr, bool use_readline);
25
37
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
26
char *serial;
38
int monitor_init(MonitorOptions *opts, Error **errp);
27
NvmeNamespace *namespaces;
39
int monitor_init_opts(QemuOpts *opts, Error **errp);
28
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
40
void monitor_cleanup(void);
41
diff --git a/chardev/char.c b/chardev/char.c
29
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/block/nvme.c
43
--- a/chardev/char.c
31
+++ b/hw/block/nvme.c
44
+++ b/chardev/char.c
32
@@ -XXX,XX +XXX,XX @@ static uint8_t nvme_sq_empty(NvmeSQueue *sq)
45
@@ -XXX,XX +XXX,XX @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
33
return sq->head == sq->tail;
46
47
if (qemu_opt_get_bool(opts, "mux", 0)) {
48
assert(permit_mux_mon);
49
- monitor_init_hmp(chr, true);
50
+ monitor_init_hmp(chr, true, &err);
51
+ if (err) {
52
+ error_report_err(err);
53
+ object_unparent(OBJECT(chr));
54
+ chr = NULL;
55
+ goto out;
56
+ }
57
}
58
59
out:
60
diff --git a/gdbstub.c b/gdbstub.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/gdbstub.c
63
+++ b/gdbstub.c
64
@@ -XXX,XX +XXX,XX @@ int gdbserver_start(const char *device)
65
/* Initialize a monitor terminal for gdb */
66
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
67
NULL, NULL, &error_abort);
68
- monitor_init_hmp(mon_chr, false);
69
+ monitor_init_hmp(mon_chr, false, &error_abort);
70
} else {
71
qemu_chr_fe_deinit(&s->chr, true);
72
mon_chr = s->mon_chr;
73
diff --git a/monitor/hmp.c b/monitor/hmp.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/monitor/hmp.c
76
+++ b/monitor/hmp.c
77
@@ -XXX,XX +XXX,XX @@ static void monitor_readline_flush(void *opaque)
78
monitor_flush(&mon->common);
34
}
79
}
35
80
36
-static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
81
-void monitor_init_hmp(Chardev *chr, bool use_readline)
37
+static void nvme_irq_check(NvmeCtrl *n)
82
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp)
38
+{
83
{
39
+ if (msix_enabled(&(n->parent_obj))) {
84
MonitorHMP *mon = g_new0(MonitorHMP, 1);
85
86
+ if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) {
87
+ g_free(mon);
40
+ return;
88
+ return;
41
+ }
89
+ }
42
+ if (~n->bar.intms & n->irq_status) {
43
+ pci_irq_assert(&n->parent_obj);
44
+ } else {
45
+ pci_irq_deassert(&n->parent_obj);
46
+ }
47
+}
48
+
90
+
49
+static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq)
91
monitor_data_init(&mon->common, false, false, false);
92
- qemu_chr_fe_init(&mon->common.chr, chr, &error_abort);
93
94
mon->use_readline = use_readline;
95
if (mon->use_readline) {
96
diff --git a/monitor/monitor.c b/monitor/monitor.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/monitor/monitor.c
99
+++ b/monitor/monitor.c
100
@@ -XXX,XX +XXX,XX @@ int monitor_init(MonitorOptions *opts, Error **errp)
101
warn_report("'pretty' is deprecated for HMP monitors, it has no "
102
"effect and will be removed in future versions");
103
}
104
- monitor_init_hmp(chr, true);
105
+ monitor_init_hmp(chr, true, &local_err);
106
break;
107
default:
108
g_assert_not_reached();
109
diff --git a/stubs/monitor.c b/stubs/monitor.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/stubs/monitor.c
112
+++ b/stubs/monitor.c
113
@@ -XXX,XX +XXX,XX @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
114
return -1;
115
}
116
117
-void monitor_init_hmp(Chardev *chr, bool use_readline)
118
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp)
50
{
119
{
51
if (cq->irq_enabled) {
52
if (msix_enabled(&(n->parent_obj))) {
53
@@ -XXX,XX +XXX,XX @@ static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq)
54
msix_notify(&(n->parent_obj), cq->vector);
55
} else {
56
trace_nvme_irq_pin();
57
- pci_irq_pulse(&n->parent_obj);
58
+ assert(cq->cqid < 64);
59
+ n->irq_status |= 1 << cq->cqid;
60
+ nvme_irq_check(n);
61
}
62
} else {
63
trace_nvme_irq_masked();
64
}
65
}
120
}
66
121
67
+static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq)
122
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
68
+{
123
index XXXXXXX..XXXXXXX 100644
69
+ if (cq->irq_enabled) {
124
--- a/tests/test-util-sockets.c
70
+ if (msix_enabled(&(n->parent_obj))) {
125
+++ b/tests/test-util-sockets.c
71
+ return;
126
@@ -XXX,XX +XXX,XX @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
72
+ } else {
127
__thread Monitor *cur_mon;
73
+ assert(cq->cqid < 64);
128
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
74
+ n->irq_status &= ~(1 << cq->cqid);
129
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {}
75
+ nvme_irq_check(n);
130
-void monitor_init_hmp(Chardev *chr, bool use_readline) {}
76
+ }
131
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) {}
77
+ }
132
78
+}
133
79
+
134
static void test_socket_fd_pass_name_good(void)
80
static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
81
uint64_t prp2, uint32_t len, NvmeCtrl *n)
82
{
83
@@ -XXX,XX +XXX,XX @@ static void nvme_post_cqes(void *opaque)
84
sizeof(req->cqe));
85
QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
86
}
87
- nvme_isr_notify(n, cq);
88
+ nvme_irq_assert(n, cq);
89
}
90
91
static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
92
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
93
n->bar.intmc = n->bar.intms;
94
trace_nvme_mmio_intm_set(data & 0xffffffff,
95
n->bar.intmc);
96
+ nvme_irq_check(n);
97
break;
98
case 0x10: /* INTMC */
99
if (unlikely(msix_enabled(&(n->parent_obj)))) {
100
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
101
n->bar.intmc = n->bar.intms;
102
trace_nvme_mmio_intm_clr(data & 0xffffffff,
103
n->bar.intmc);
104
+ nvme_irq_check(n);
105
break;
106
case 0x14: /* CC */
107
trace_nvme_mmio_cfg(data & 0xffffffff);
108
@@ -XXX,XX +XXX,XX @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
109
timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
110
}
111
112
- if (cq->tail != cq->head) {
113
- nvme_isr_notify(n, cq);
114
+ if (cq->tail == cq->head) {
115
+ nvme_irq_deassert(n, cq);
116
}
117
} else {
118
/* Submission queue doorbell write */
119
--
135
--
120
2.13.6
136
2.20.1
121
137
122
138
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
Add a new parameter allow_hmp to monitor_init() so that the storage
2
daemon can disable HMP.
2
3
3
184 does not need an image, so don't use one.
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Message-Id: <20200224143008.13362-20-kwolf@redhat.com>
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
qapi/control.json | 3 ++-
10
include/monitor/monitor.h | 2 +-
11
monitor/monitor.c | 12 ++++++++++--
12
3 files changed, 13 insertions(+), 4 deletions(-)
4
13
5
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
diff --git a/qapi/control.json b/qapi/control.json
6
Message-id: 20171123020832.8165-16-mreitz@redhat.com
15
index XXXXXXX..XXXXXXX 100644
7
Reviewed-by: John Snow <jsnow@redhat.com>
16
--- a/qapi/control.json
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
+++ b/qapi/control.json
9
---
18
@@ -XXX,XX +XXX,XX @@
10
tests/qemu-iotests/184 | 25 ++++--------------
19
#
11
tests/qemu-iotests/184.out | 63 +++++++---------------------------------------
20
# @id: Name of the monitor
12
2 files changed, 14 insertions(+), 74 deletions(-)
21
#
13
22
-# @mode: Selects the monitor mode (default: readline)
14
diff --git a/tests/qemu-iotests/184 b/tests/qemu-iotests/184
23
+# @mode: Selects the monitor mode (default: readline in the system
15
index XXXXXXX..XXXXXXX 100755
24
+# emulator, control in qemu-storage-daemon)
16
--- a/tests/qemu-iotests/184
25
#
17
+++ b/tests/qemu-iotests/184
26
# @pretty: Enables pretty printing (QMP only)
18
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
27
#
19
here=`pwd`
28
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
20
status=1    # failure is the default!
29
index XXXXXXX..XXXXXXX 100644
21
30
--- a/include/monitor/monitor.h
22
-_cleanup()
31
+++ b/include/monitor/monitor.h
23
-{
32
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals(void);
24
- _cleanup_test_img
33
void monitor_init_globals_core(void);
25
-}
34
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
26
-trap "_cleanup; exit \$status" 0 1 2 3 15
35
void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
27
+trap "exit \$status" 0 1 2 3 15
36
-int monitor_init(MonitorOptions *opts, Error **errp);
28
37
+int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp);
29
# get standard environment, filters and checks
38
int monitor_init_opts(QemuOpts *opts, Error **errp);
30
. ./common.rc
39
void monitor_cleanup(void);
31
. ./common.filter
40
32
41
diff --git a/monitor/monitor.c b/monitor/monitor.c
33
-_supported_fmt qcow2
42
index XXXXXXX..XXXXXXX 100644
34
-_supported_proto file
43
--- a/monitor/monitor.c
35
_supported_os Linux
44
+++ b/monitor/monitor.c
36
45
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals_core(void)
37
function do_run_qemu()
46
NULL);
38
@@ -XXX,XX +XXX,XX @@ function run_qemu()
39
| _filter_actual_image_size
40
}
47
}
41
48
42
-_make_test_img 64M
49
-int monitor_init(MonitorOptions *opts, Error **errp)
43
test_throttle=$($QEMU_IMG --help|grep throttle)
50
+int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp)
44
[ "$test_throttle" = "" ] && _supported_fmt throttle
51
{
45
52
Chardev *chr;
46
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
53
Error *local_err = NULL;
47
{ "execute": "qmp_capabilities" }
54
@@ -XXX,XX +XXX,XX @@ int monitor_init(MonitorOptions *opts, Error **errp)
48
{ "execute": "blockdev-add",
55
return -1;
49
"arguments": {
56
}
50
- "driver": "$IMGFMT",
57
51
- "node-name": "disk0",
58
+ if (!opts->has_mode) {
52
- "file": {
59
+ opts->mode = allow_hmp ? MONITOR_MODE_READLINE : MONITOR_MODE_CONTROL;
53
- "driver": "file",
60
+ }
54
- "filename": "$TEST_IMG"
61
+
55
- }
62
switch (opts->mode) {
56
+ "driver": "null-co",
63
case MONITOR_MODE_CONTROL:
57
+ "node-name": "disk0"
64
monitor_init_qmp(chr, opts->pretty, &local_err);
58
}
65
break;
59
}
66
case MONITOR_MODE_READLINE:
60
{ "execute": "object-add",
67
+ if (!allow_hmp) {
61
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
68
+ error_setg(errp, "Only QMP is supported");
62
{ "execute": "qmp_capabilities" }
69
+ return -1;
63
{ "execute": "blockdev-add",
70
+ }
64
"arguments": {
71
if (opts->pretty) {
65
- "driver": "$IMGFMT",
72
warn_report("'pretty' is deprecated for HMP monitors, it has no "
66
- "node-name": "disk0",
73
"effect and will be removed in future versions");
67
- "file": {
74
@@ -XXX,XX +XXX,XX @@ int monitor_init_opts(QemuOpts *opts, Error **errp)
68
- "driver": "file",
75
goto out;
69
- "filename": "$TEST_IMG"
76
}
70
- }
77
71
+ "driver": "null-co",
78
- monitor_init(options, &local_err);
72
+ "node-name": "disk0"
79
+ monitor_init(options, true, &local_err);
73
}
80
qapi_free_MonitorOptions(options);
74
}
81
75
{ "execute": "blockdev-add",
82
out:
76
diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/qemu-iotests/184.out
79
+++ b/tests/qemu-iotests/184.out
80
@@ -XXX,XX +XXX,XX @@
81
QA output created by 184
82
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
83
84
== checking interface ==
85
Testing:
86
@@ -XXX,XX +XXX,XX @@ Testing:
87
"iops_rd": 0,
88
"detect_zeroes": "off",
89
"image": {
90
- "virtual-size": 67108864,
91
- "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}",
92
- "cluster-size": 65536,
93
- "format": "throttle",
94
- "actual-size": SIZE,
95
- "dirty-flag": false
96
+ "virtual-size": 1073741824,
97
+ "filename": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"null-co\"}}",
98
+ "format": "throttle"
99
},
100
"iops_wr": 0,
101
"ro": false,
102
@@ -XXX,XX +XXX,XX @@ Testing:
103
"direct": false,
104
"writeback": true
105
},
106
- "file": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"qcow2\", \"file\": {\"driver\": \"file\", \"filename\": \"TEST_DIR/t.qcow2\"}}}",
107
+ "file": "json:{\"throttle-group\": \"group0\", \"driver\": \"throttle\", \"file\": {\"driver\": \"null-co\"}}",
108
"encryption_key_missing": false
109
},
110
{
111
"iops_rd": 0,
112
"detect_zeroes": "off",
113
"image": {
114
- "virtual-size": 67108864,
115
- "filename": "TEST_DIR/t.qcow2",
116
- "cluster-size": 65536,
117
- "format": "qcow2",
118
- "actual-size": SIZE,
119
- "format-specific": {
120
- "type": "qcow2",
121
- "data": {
122
- "compat": "1.1",
123
- "lazy-refcounts": false,
124
- "refcount-bits": 16,
125
- "corrupt": false
126
- }
127
- },
128
- "dirty-flag": false
129
+ "virtual-size": 1073741824,
130
+ "filename": "null-co://",
131
+ "format": "null-co"
132
},
133
"iops_wr": 0,
134
"ro": false,
135
"node-name": "disk0",
136
"backing_file_depth": 0,
137
- "drv": "qcow2",
138
+ "drv": "null-co",
139
"iops": 0,
140
"bps_wr": 0,
141
"write_threshold": 0,
142
@@ -XXX,XX +XXX,XX @@ Testing:
143
"direct": false,
144
"writeback": true
145
},
146
- "file": "TEST_DIR/t.qcow2",
147
- "encryption_key_missing": false
148
- },
149
- {
150
- "iops_rd": 0,
151
- "detect_zeroes": "off",
152
- "image": {
153
- "virtual-size": 197120,
154
- "filename": "TEST_DIR/t.qcow2",
155
- "format": "file",
156
- "actual-size": SIZE,
157
- "dirty-flag": false
158
- },
159
- "iops_wr": 0,
160
- "ro": false,
161
- "node-name": "NODE_NAME",
162
- "backing_file_depth": 0,
163
- "drv": "file",
164
- "iops": 0,
165
- "bps_wr": 0,
166
- "write_threshold": 0,
167
- "encrypted": false,
168
- "bps": 0,
169
- "bps_rd": 0,
170
- "cache": {
171
- "no-flush": false,
172
- "direct": false,
173
- "writeback": true
174
- },
175
- "file": "TEST_DIR/t.qcow2",
176
+ "file": "null-co://",
177
"encryption_key_missing": false
178
}
179
]
180
--
83
--
181
2.13.6
84
2.20.1
182
85
183
86
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
This adds and parses the --monitor option, so that a QMP monitor can be
2
2
used in the storage daemon. The monitor offers commands defined in the
3
When originally written, test 177 explicitly took care to run
3
QAPI schema at storage-daemon/qapi/qapi-schema.json.
4
with compat=0.10. Then I botched my own test in commit
4
5
81c219ac and f0a9c18f, by adding additional actions that require
5
The --monitor options currently allows to create multiple monitors with
6
v3 images. Split out the new code into a new v3-only test, 204,
6
the same ID. This part of the interface is considered unstable. We will
7
and revert 177 back to its original state other than a new comment.
7
reject such configurations as soon as we have a design for the monitor
8
8
subsystem to perform these checks. (In the system emulator, we depend on
9
Reported-by: Max Reitz <mreitz@redhat.com>
9
QemuOpts rejecting duplicate IDs.)
10
Signed-off-by: Eric Blake <eblake@redhat.com>
10
11
Message-id: 20180117165420.15946-2-eblake@redhat.com
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200224143008.13362-21-kwolf@redhat.com>
13
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
15
---
14
tests/qemu-iotests/177 | 20 +++-----
16
qapi/transaction.json | 2 +-
15
tests/qemu-iotests/177.out | 22 ++-------
17
qemu-storage-daemon.c | 47 ++++++++++++++++++++++++++--
16
tests/qemu-iotests/204 | 119 +++++++++++++++++++++++++++++++++++++++++++++
18
scripts/qapi/gen.py | 5 +++
17
tests/qemu-iotests/204.out | 63 ++++++++++++++++++++++++
19
Makefile | 33 +++++++++++++++++++
18
tests/qemu-iotests/group | 1 +
20
Makefile.objs | 4 +--
19
5 files changed, 193 insertions(+), 32 deletions(-)
21
monitor/Makefile.objs | 2 ++
20
create mode 100755 tests/qemu-iotests/204
22
qapi/Makefile.objs | 5 +++
21
create mode 100644 tests/qemu-iotests/204.out
23
storage-daemon/Makefile.objs | 1 +
22
24
storage-daemon/qapi/Makefile.objs | 1 +
23
diff --git a/tests/qemu-iotests/177 b/tests/qemu-iotests/177
25
storage-daemon/qapi/qapi-schema.json | 26 +++++++++++++++
24
index XXXXXXX..XXXXXXX 100755
26
10 files changed, 121 insertions(+), 5 deletions(-)
25
--- a/tests/qemu-iotests/177
27
create mode 100644 storage-daemon/Makefile.objs
26
+++ b/tests/qemu-iotests/177
28
create mode 100644 storage-daemon/qapi/Makefile.objs
29
create mode 100644 storage-daemon/qapi/qapi-schema.json
30
31
diff --git a/qapi/transaction.json b/qapi/transaction.json
32
index XXXXXXX..XXXXXXX 100644
33
--- a/qapi/transaction.json
34
+++ b/qapi/transaction.json
27
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
28
#
36
# = Transactions
29
# Test corner cases with unusual block geometries
37
##
30
#
38
31
-# Copyright (C) 2016-2017 Red Hat, Inc.
39
-{ 'include': 'block.json' }
32
+# Copyright (C) 2016-2018 Red Hat, Inc.
40
+{ 'include': 'block-core.json' }
33
#
41
34
# This program is free software; you can redistribute it and/or modify
42
##
35
# it under the terms of the GNU General Public License as published by
43
# @Abort:
36
@@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15
44
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
37
. ./common.rc
45
index XXXXXXX..XXXXXXX 100644
38
. ./common.filter
46
--- a/qemu-storage-daemon.c
39
47
+++ b/qemu-storage-daemon.c
40
+# This test is runnable under compat=0.10; see test 204 for additional
48
@@ -XXX,XX +XXX,XX @@
41
+# tests specific to compat=1.1.
49
#include "block/nbd.h"
42
+
50
#include "chardev/char.h"
43
_supported_fmt qcow2
51
#include "crypto/init.h"
44
_supported_proto file
52
+#include "monitor/monitor.h"
45
53
+#include "monitor/monitor-internal.h"
46
CLUSTER_SIZE=1M
54
47
size=128M
55
#include "qapi/error.h"
48
options=driver=blkdebug,image.driver=qcow2
56
-#include "qapi/qapi-commands-block.h"
49
-nested_opts=image.file.driver=file,image.file.filename=$TEST_IMG
57
-#include "qapi/qapi-commands-block-core.h"
50
58
#include "qapi/qapi-visit-block.h"
51
echo
59
#include "qapi/qapi-visit-block-core.h"
52
echo "== setting up files =="
60
+#include "qapi/qapi-visit-control.h"
53
@@ -XXX,XX +XXX,XX @@ echo "== setting up files =="
61
#include "qapi/qmp/qdict.h"
54
TEST_IMG="$TEST_IMG.base" _make_test_img $size
62
+#include "qapi/qmp/qstring.h"
55
$QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io
63
#include "qapi/qobject-input-visitor.h"
56
_make_test_img -b "$TEST_IMG.base"
64
57
-$QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io
65
#include "qemu-common.h"
58
+$QEMU_IO -c "write -P 22 0 $size" "$TEST_IMG" | _filter_qemu_io
66
@@ -XXX,XX +XXX,XX @@
59
67
#include "qemu/option.h"
60
# Limited to 64k max-transfer
68
#include "qom/object_interfaces.h"
61
echo
69
62
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
70
+#include "storage-daemon/qapi/qapi-commands.h"
63
-c "discard 80000001 30M" | _filter_qemu_io
71
+#include "storage-daemon/qapi/qapi-init-commands.h"
64
72
+
65
echo
73
#include "sysemu/runstate.h"
66
-echo "== block status smaller than alignment =="
74
#include "trace/control.h"
67
-limits=align=4k
75
68
-$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
76
@@ -XXX,XX +XXX,XX @@ void qemu_system_killed(int signal, pid_t pid)
69
-     -c "alloc 1 1" -c "alloc 0x6dffff0 1000" -c "alloc 127m 5P" \
77
exit_requested = true;
70
-     -c map | _filter_qemu_io
71
-
72
-echo
73
echo "== verify image content =="
74
75
function verify_io()
76
@@ -XXX,XX +XXX,XX @@ function verify_io()
77
echo read -P 0 32M 32M
78
echo read -P 22 64M 13M
79
echo read -P $discarded 77M 29M
80
- echo read -P 22 106M 4M
81
- echo read -P 11 110M 18M
82
+ echo read -P 22 106M 22M
83
}
78
}
84
79
85
verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
80
+void qmp_quit(Error **errp)
86
-$QEMU_IMG map --image-opts "$options,$nested_opts,align=4k" \
87
- | _filter_qemu_img_map
88
89
_check_test_img
90
91
diff --git a/tests/qemu-iotests/177.out b/tests/qemu-iotests/177.out
92
index XXXXXXX..XXXXXXX 100644
93
--- a/tests/qemu-iotests/177.out
94
+++ b/tests/qemu-iotests/177.out
95
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
96
wrote 134217728/134217728 bytes at offset 0
97
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
98
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
99
-wrote 115343360/115343360 bytes at offset 0
100
-110 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
101
+wrote 134217728/134217728 bytes at offset 0
102
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
103
104
== constrained alignment and max-transfer ==
105
wrote 131072/131072 bytes at offset 1000
106
@@ -XXX,XX +XXX,XX @@ wrote 33554432/33554432 bytes at offset 33554432
107
discard 31457280/31457280 bytes at offset 80000001
108
30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
110
-== block status smaller than alignment ==
111
-1/1 bytes allocated at offset 1 bytes
112
-16/1000 bytes allocated at offset 110 MiB
113
-0/1048576 bytes allocated at offset 127 MiB
114
-110 MiB (0x6e00000) bytes allocated at offset 0 bytes (0x0)
115
-18 MiB (0x1200000) bytes not allocated at offset 110 MiB (0x6e00000)
116
-
117
== verify image content ==
118
read 1000/1000 bytes at offset 0
119
1000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
120
@@ -XXX,XX +XXX,XX @@ read 13631488/13631488 bytes at offset 67108864
121
13 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
122
read 30408704/30408704 bytes at offset 80740352
123
29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
124
-read 4194304/4194304 bytes at offset 111149056
125
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
126
-read 18874368/18874368 bytes at offset 115343360
127
-18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
128
-Offset Length File
129
-0 0x800000 TEST_DIR/t.IMGFMT
130
-0x900000 0x2400000 TEST_DIR/t.IMGFMT
131
-0x3c00000 0x1100000 TEST_DIR/t.IMGFMT
132
-0x6a00000 0x400000 TEST_DIR/t.IMGFMT
133
+read 23068672/23068672 bytes at offset 111149056
134
+22 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
135
No errors were found on the image.
136
*** done
137
diff --git a/tests/qemu-iotests/204 b/tests/qemu-iotests/204
138
new file mode 100755
139
index XXXXXXX..XXXXXXX
140
--- /dev/null
141
+++ b/tests/qemu-iotests/204
142
@@ -XXX,XX +XXX,XX @@
143
+#!/bin/bash
144
+#
145
+# Test corner cases with unusual block geometries
146
+#
147
+# Copyright (C) 2016-2018 Red Hat, Inc.
148
+#
149
+# This program is free software; you can redistribute it and/or modify
150
+# it under the terms of the GNU General Public License as published by
151
+# the Free Software Foundation; either version 2 of the License, or
152
+# (at your option) any later version.
153
+#
154
+# This program is distributed in the hope that it will be useful,
155
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
156
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
157
+# GNU General Public License for more details.
158
+#
159
+# You should have received a copy of the GNU General Public License
160
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
161
+#
162
+
163
+# creator
164
+owner=eblake@redhat.com
165
+
166
+seq=`basename $0`
167
+echo "QA output created by $seq"
168
+
169
+here=`pwd`
170
+status=1    # failure is the default!
171
+
172
+_cleanup()
173
+{
81
+{
174
+    _cleanup_test_img
82
+ exit_requested = true;
175
+}
83
+}
176
+trap "_cleanup; exit \$status" 0 1 2 3 15
84
+
177
+
85
static void help(void)
178
+# get standard environment, filters and checks
86
{
179
+. ./common.rc
87
printf(
180
+. ./common.filter
88
@@ -XXX,XX +XXX,XX @@ static void help(void)
181
+
89
" export the specified block node over NBD\n"
182
+_supported_fmt qcow2
90
" (requires --nbd-server)\n"
183
+_supported_proto file
91
"\n"
184
+# This test assumes that discard leaves zero clusters; see test 177 for
92
+" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
185
+# other tests that also work in older images
93
+" configure a QMP monitor\n"
186
+_unsupported_imgopts 'compat=0.10'
94
+"\n"
187
+
95
" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
188
+CLUSTER_SIZE=1M
96
" [,tls-creds=<id>][,tls-authz=<id>]\n"
189
+size=128M
97
" --nbd-server addr.type=unix,addr.path=<path>\n"
190
+options=driver=blkdebug,image.driver=qcow2
98
@@ -XXX,XX +XXX,XX @@ enum {
191
+nested_opts=image.file.driver=file,image.file.filename=$TEST_IMG
99
OPTION_BLOCKDEV = 256,
192
+
100
OPTION_CHARDEV,
193
+echo
101
OPTION_EXPORT,
194
+echo "== setting up files =="
102
+ OPTION_MONITOR,
195
+
103
OPTION_NBD_SERVER,
196
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
104
OPTION_OBJECT,
197
+$QEMU_IO -c "write -P 11 0 $size" "$TEST_IMG.base" | _filter_qemu_io
105
};
198
+_make_test_img -b "$TEST_IMG.base"
106
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_object_opts = {
199
+$QEMU_IO -c "write -P 22 0 110M" "$TEST_IMG" | _filter_qemu_io
107
},
200
+
108
};
201
+# Limited to 64k max-transfer
109
202
+echo
110
+static void init_qmp_commands(void)
203
+echo "== constrained alignment and max-transfer =="
204
+limits=align=4k,max-transfer=64k
205
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
206
+ -c "write -P 33 1000 128k" -c "read -P 33 1000 128k" | _filter_qemu_io
207
+
208
+echo
209
+echo "== write zero with constrained max-transfer =="
210
+limits=align=512,max-transfer=64k,opt-write-zero=$CLUSTER_SIZE
211
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
212
+ -c "write -z 8003584 2093056" | _filter_qemu_io
213
+
214
+# non-power-of-2 write-zero/discard alignments
215
+echo
216
+echo "== non-power-of-2 write zeroes limits =="
217
+
218
+limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-discard=15M
219
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
220
+ -c "write -z 32M 32M" | _filter_qemu_io
221
+
222
+echo
223
+echo "== non-power-of-2 discard limits =="
224
+
225
+limits=align=512,opt-write-zero=15M,max-write-zero=15M,opt-discard=15M,max-discard=15M
226
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
227
+ -c "discard 80000001 30M" | _filter_qemu_io
228
+
229
+echo
230
+echo "== block status smaller than alignment =="
231
+limits=align=4k
232
+$QEMU_IO -c "open -o $options,$limits blkdebug::$TEST_IMG" \
233
+     -c "alloc 1 1" -c "alloc 0x6dffff0 1000" -c "alloc 127m 5P" \
234
+     -c map | _filter_qemu_io
235
+
236
+echo
237
+echo "== verify image content =="
238
+
239
+function verify_io()
240
+{
111
+{
241
+ echo read -P 22 0 1000
112
+ qmp_init_marshal(&qmp_commands);
242
+ echo read -P 33 1000 128k
113
+ qmp_register_command(&qmp_commands, "query-qmp-schema",
243
+ echo read -P 22 132072 7871512
114
+ qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
244
+ echo read -P 0 8003584 2093056
115
+
245
+ echo read -P 22 10096640 23457792
116
+ QTAILQ_INIT(&qmp_cap_negotiation_commands);
246
+ echo read -P 0 32M 32M
117
+ qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
247
+ echo read -P 22 64M 13M
118
+ qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
248
+ echo read -P 0 77M 29M
249
+ echo read -P 22 106M 4M
250
+ echo read -P 11 110M 18M
251
+}
119
+}
252
+
120
+
253
+verify_io | $QEMU_IO -r "$TEST_IMG" | _filter_qemu_io
121
static void init_export(BlockExport *export, Error **errp)
254
+$QEMU_IMG map --image-opts "$options,$nested_opts,align=4k" \
122
{
255
+ | _filter_qemu_img_map
123
switch (export->type) {
256
+
124
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
257
+_check_test_img
125
{"chardev", required_argument, NULL, OPTION_CHARDEV},
258
+
126
{"export", required_argument, NULL, OPTION_EXPORT},
259
+# success, all done
127
{"help", no_argument, NULL, 'h'},
260
+echo "*** done"
128
+ {"monitor", required_argument, NULL, OPTION_MONITOR},
261
+status=0
129
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
262
diff --git a/tests/qemu-iotests/204.out b/tests/qemu-iotests/204.out
130
{"object", required_argument, NULL, OPTION_OBJECT},
131
{"trace", required_argument, NULL, 'T'},
132
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
133
qapi_free_BlockExport(export);
134
break;
135
}
136
+ case OPTION_MONITOR:
137
+ {
138
+ Visitor *v;
139
+ MonitorOptions *monitor;
140
+
141
+ v = qobject_input_visitor_new_str(optarg, "chardev",
142
+ &error_fatal);
143
+ visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal);
144
+ visit_free(v);
145
+
146
+ /* TODO Catch duplicate monitor IDs */
147
+ monitor_init(monitor, false, &error_fatal);
148
+ qapi_free_MonitorOptions(monitor);
149
+ break;
150
+ }
151
case OPTION_NBD_SERVER:
152
{
153
Visitor *v;
154
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
155
qemu_add_opts(&qemu_trace_opts);
156
qcrypto_init(&error_fatal);
157
bdrv_init();
158
+ monitor_init_globals_core();
159
+ init_qmp_commands();
160
161
if (!trace_init_backends()) {
162
return EXIT_FAILURE;
163
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
164
index XXXXXXX..XXXXXXX 100644
165
--- a/scripts/qapi/gen.py
166
+++ b/scripts/qapi/gen.py
167
@@ -XXX,XX +XXX,XX @@ class QAPIGen:
168
return ''
169
170
def write(self, output_dir):
171
+ # Include paths starting with ../ are used to reuse modules of the main
172
+ # schema in specialised schemas. Don't overwrite the files that are
173
+ # already generated for the main schema.
174
+ if self.fname.startswith('../'):
175
+ return
176
pathname = os.path.join(output_dir, self.fname)
177
odir = os.path.dirname(pathname)
178
if odir:
179
diff --git a/Makefile b/Makefile
180
index XXXXXXX..XXXXXXX 100644
181
--- a/Makefile
182
+++ b/Makefile
183
@@ -XXX,XX +XXX,XX @@ GENERATED_QAPI_FILES += $(QAPI_MODULES:%=qapi/qapi-events-%.c)
184
GENERATED_QAPI_FILES += qapi/qapi-introspect.c qapi/qapi-introspect.h
185
GENERATED_QAPI_FILES += qapi/qapi-doc.texi
186
187
+# The following list considers only the storage daemon main module. All other
188
+# modules are currently shared with the main schema, so we don't actually
189
+# generate additional files.
190
+
191
+GENERATED_STORAGE_DAEMON_QAPI_FILES = storage-daemon/qapi/qapi-commands.h
192
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-commands.c
193
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.h
194
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-emit-events.c
195
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.h
196
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-events.c
197
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.h
198
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-init-commands.c
199
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.h
200
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-introspect.c
201
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.h
202
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-types.c
203
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.h
204
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-visit.c
205
+GENERATED_STORAGE_DAEMON_QAPI_FILES += storage-daemon/qapi/qapi-doc.texi
206
+
207
generated-files-y += $(GENERATED_QAPI_FILES)
208
+generated-files-y += $(GENERATED_STORAGE_DAEMON_QAPI_FILES)
209
210
generated-files-y += trace/generated-tcg-tracers.h
211
212
@@ -XXX,XX +XXX,XX @@ qapi-gen-timestamp: $(qapi-modules) $(qapi-py)
213
        "GEN","$(@:%-timestamp=%)")
214
    @>$@
215
216
+qapi-modules-storage-daemon = \
217
+    $(SRC_PATH)/storage-daemon/qapi/qapi-schema.json \
218
+ $(QAPI_MODULES_STORAGE_DAEMON:%=$(SRC_PATH)/qapi/%.json)
219
+
220
+$(GENERATED_STORAGE_DAEMON_QAPI_FILES): storage-daemon/qapi/qapi-gen-timestamp ;
221
+storage-daemon/qapi/qapi-gen-timestamp: $(qapi-modules-storage-daemon) $(qapi-py)
222
+    $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \
223
+        -o "storage-daemon/qapi" $<, \
224
+        "GEN","$(@:%-timestamp=%)")
225
+    @>$@
226
+
227
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qapi-commands.h qga-qapi-init-commands.h)
228
$(qga-obj-y): $(QGALIB_GEN)
229
230
@@ -XXX,XX +XXX,XX @@ clean: recurse-clean
231
    rm -f trace/generated-tracers-dtrace.h*
232
    rm -f $(foreach f,$(generated-files-y),$(f) $(f)-timestamp)
233
    rm -f qapi-gen-timestamp
234
+    rm -f storage-daemon/qapi/qapi-gen-timestamp
235
    rm -rf qga/qapi-generated
236
    rm -f config-all-devices.mak
237
238
diff --git a/Makefile.objs b/Makefile.objs
239
index XXXXXXX..XXXXXXX 100644
240
--- a/Makefile.objs
241
+++ b/Makefile.objs
242
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
243
# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are
244
# used for system emulation, too, but specified separately there)
245
246
-storage-daemon-obj-y = block/ qom/
247
-storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o
248
+storage-daemon-obj-y = block/ monitor/ qapi/ qom/ storage-daemon/
249
+storage-daemon-obj-y += blockdev.o blockdev-nbd.o iothread.o job-qmp.o
250
storage-daemon-obj-$(CONFIG_WIN32) += os-win32.o
251
storage-daemon-obj-$(CONFIG_POSIX) += os-posix.o
252
253
diff --git a/monitor/Makefile.objs b/monitor/Makefile.objs
254
index XXXXXXX..XXXXXXX 100644
255
--- a/monitor/Makefile.objs
256
+++ b/monitor/Makefile.objs
257
@@ -XXX,XX +XXX,XX @@ obj-y += misc.o
258
common-obj-y += monitor.o qmp.o hmp.o
259
common-obj-y += qmp-cmds.o qmp-cmds-control.o
260
common-obj-y += hmp-cmds.o
261
+
262
+storage-daemon-obj-y += monitor.o qmp.o qmp-cmds-control.o
263
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
264
index XXXXXXX..XXXXXXX 100644
265
--- a/qapi/Makefile.objs
266
+++ b/qapi/Makefile.objs
267
@@ -XXX,XX +XXX,XX @@ obj-y += qapi-events.o
268
obj-y += $(QAPI_TARGET_MODULES:%=qapi-commands-%.o)
269
obj-y += qapi-commands.o
270
obj-y += qapi-init-commands.o
271
+
272
+QAPI_MODULES_STORAGE_DAEMON = block-core char common control crypto
273
+QAPI_MODULES_STORAGE_DAEMON += introspect job qom sockets pragma transaction
274
+
275
+storage-daemon-obj-y += $(QAPI_MODULES_STORAGE_DAEMON:%=qapi-commands-%.o)
276
diff --git a/storage-daemon/Makefile.objs b/storage-daemon/Makefile.objs
263
new file mode 100644
277
new file mode 100644
264
index XXXXXXX..XXXXXXX
278
index XXXXXXX..XXXXXXX
265
--- /dev/null
279
--- /dev/null
266
+++ b/tests/qemu-iotests/204.out
280
+++ b/storage-daemon/Makefile.objs
281
@@ -0,0 +1 @@
282
+storage-daemon-obj-y += qapi/
283
diff --git a/storage-daemon/qapi/Makefile.objs b/storage-daemon/qapi/Makefile.objs
284
new file mode 100644
285
index XXXXXXX..XXXXXXX
286
--- /dev/null
287
+++ b/storage-daemon/qapi/Makefile.objs
288
@@ -0,0 +1 @@
289
+storage-daemon-obj-y += qapi-commands.o qapi-init-commands.o qapi-introspect.o
290
diff --git a/storage-daemon/qapi/qapi-schema.json b/storage-daemon/qapi/qapi-schema.json
291
new file mode 100644
292
index XXXXXXX..XXXXXXX
293
--- /dev/null
294
+++ b/storage-daemon/qapi/qapi-schema.json
267
@@ -XXX,XX +XXX,XX @@
295
@@ -XXX,XX +XXX,XX @@
268
+QA output created by 204
296
+# -*- Mode: Python -*-
269
+
297
+
270
+== setting up files ==
298
+# Note that modules are shared with the QEMU main schema under the assumption
271
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
299
+# that the storage daemon schema is a subset of the main schema. For the shared
272
+wrote 134217728/134217728 bytes at offset 0
300
+# modules, no code is generated here, but we reuse the code files generated
273
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
301
+# from the main schema.
274
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
302
+#
275
+wrote 115343360/115343360 bytes at offset 0
303
+# If you wish to extend the storage daemon schema to contain things that are
276
+110 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
304
+# not in the main schema, be aware that array types of types defined in shared
277
+
305
+# modules are only generated if an array of the respective type is already used
278
+== constrained alignment and max-transfer ==
306
+# in the main schema. Therefore, if you use such arrays, you may need to define
279
+wrote 131072/131072 bytes at offset 1000
307
+# the array type in the main schema, even if it is unused outside of the
280
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+# storage daemon.
281
+read 131072/131072 bytes at offset 1000
309
+
282
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
310
+{ 'include': '../../qapi/pragma.json' }
283
+
311
+
284
+== write zero with constrained max-transfer ==
312
+{ 'include': '../../qapi/block-core.json' }
285
+wrote 2093056/2093056 bytes at offset 8003584
313
+{ 'include': '../../qapi/char.json' }
286
+1.996 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
314
+{ 'include': '../../qapi/common.json' }
287
+
315
+{ 'include': '../../qapi/control.json' }
288
+== non-power-of-2 write zeroes limits ==
316
+{ 'include': '../../qapi/crypto.json' }
289
+wrote 33554432/33554432 bytes at offset 33554432
317
+{ 'include': '../../qapi/introspect.json' }
290
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
318
+{ 'include': '../../qapi/job.json' }
291
+
319
+{ 'include': '../../qapi/qom.json' }
292
+== non-power-of-2 discard limits ==
320
+{ 'include': '../../qapi/sockets.json' }
293
+discard 31457280/31457280 bytes at offset 80000001
321
+{ 'include': '../../qapi/transaction.json' }
294
+30 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
295
+
296
+== block status smaller than alignment ==
297
+1/1 bytes allocated at offset 1 bytes
298
+16/1000 bytes allocated at offset 110 MiB
299
+0/1048576 bytes allocated at offset 127 MiB
300
+110 MiB (0x6e00000) bytes allocated at offset 0 bytes (0x0)
301
+18 MiB (0x1200000) bytes not allocated at offset 110 MiB (0x6e00000)
302
+
303
+== verify image content ==
304
+read 1000/1000 bytes at offset 0
305
+1000 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
306
+read 131072/131072 bytes at offset 1000
307
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+read 7871512/7871512 bytes at offset 132072
309
+7.507 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
310
+read 2093056/2093056 bytes at offset 8003584
311
+1.996 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
312
+read 23457792/23457792 bytes at offset 10096640
313
+22.371 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
314
+read 33554432/33554432 bytes at offset 33554432
315
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
316
+read 13631488/13631488 bytes at offset 67108864
317
+13 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
318
+read 30408704/30408704 bytes at offset 80740352
319
+29 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
320
+read 4194304/4194304 bytes at offset 111149056
321
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+read 18874368/18874368 bytes at offset 115343360
323
+18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
324
+Offset Length File
325
+0 0x800000 TEST_DIR/t.IMGFMT
326
+0x900000 0x2400000 TEST_DIR/t.IMGFMT
327
+0x3c00000 0x1100000 TEST_DIR/t.IMGFMT
328
+0x6a00000 0x400000 TEST_DIR/t.IMGFMT
329
+No errors were found on the image.
330
+*** done
331
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
332
index XXXXXXX..XXXXXXX 100644
333
--- a/tests/qemu-iotests/group
334
+++ b/tests/qemu-iotests/group
335
@@ -XXX,XX +XXX,XX @@
336
201 rw auto migration
337
202 rw auto quick
338
203 rw auto
339
+204 rw auto quick
340
--
322
--
341
2.13.6
323
2.20.1
342
324
343
325
diff view generated by jsdifflib
1
From: Fam Zheng <famz@redhat.com>
1
From: Florian Florensa <fflorensa@online.net>
2
2
3
We could hit lock failure if there is a signal that makes fcntl return
3
Starting from ceph Nautilus, RBD has support for namespaces, allowing
4
-1 and errno set to EINTR. In this case we should retry.
4
for finer grain ACLs on images inside a pool, and tenant isolation.
5
5
6
Cc: qemu-stable@nongnu.org
6
In the rbd cli tool documentation, the new image-spec and snap-spec are :
7
Signed-off-by: Fam Zheng <famz@redhat.com>
7
- [pool-name/[namespace-name/]]image-name
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
- [pool-name/[namespace-name/]]image-name@snap-name
9
10
When using an non namespace's enabled qemu, it complains about not
11
finding the image called namespace-name/image-name, thus we only need to
12
parse the image once again to find if there is a '/' in its name, and if
13
there is, use what is before it as the name of the namespace to later
14
pass it to rados_ioctx_set_namespace.
15
rados_ioctx_set_namespace if called with en empty string or a null
16
pointer as the namespace parameters pretty much does nothing, as it then
17
defaults to the default namespace.
18
19
The namespace is extracted inside qemu_rbd_parse_filename, stored in the
20
qdict, and used in qemu_rbd_connect to make it work with both qemu-img,
21
and qemu itself.
22
23
Signed-off-by: Florian Florensa <fflorensa@online.net>
24
Message-Id: <20200110111513.321728-2-fflorensa@online.net>
25
Reviewed-by: Jason Dillaman <dillaman@redhat.com>
26
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
28
---
11
util/osdep.c | 4 +++-
29
qapi/block-core.json | 3 +++
12
1 file changed, 3 insertions(+), 1 deletion(-)
30
block/rbd.c | 44 +++++++++++++++++++++++++++++++-------------
31
2 files changed, 34 insertions(+), 13 deletions(-)
13
32
14
diff --git a/util/osdep.c b/util/osdep.c
33
diff --git a/qapi/block-core.json b/qapi/block-core.json
15
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
16
--- a/util/osdep.c
35
--- a/qapi/block-core.json
17
+++ b/util/osdep.c
36
+++ b/qapi/block-core.json
18
@@ -XXX,XX +XXX,XX @@ static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
37
@@ -XXX,XX +XXX,XX @@
19
.l_type = fl_type,
38
#
20
};
39
# @pool: Ceph pool name.
21
qemu_probe_lock_ops();
40
#
22
- ret = fcntl(fd, fcntl_op_setlk, &fl);
41
+# @namespace: Rados namespace name in the Ceph pool. (Since 5.0)
23
+ do {
42
+#
24
+ ret = fcntl(fd, fcntl_op_setlk, &fl);
43
# @image: Image name in the Ceph pool.
25
+ } while (ret == -1 && errno == EINTR);
44
#
26
return ret == -1 ? -errno : 0;
45
# @conf: path to Ceph configuration file. Values
27
}
46
@@ -XXX,XX +XXX,XX @@
47
##
48
{ 'struct': 'BlockdevOptionsRbd',
49
'data': { 'pool': 'str',
50
+ '*namespace': 'str',
51
'image': 'str',
52
'*conf': 'str',
53
'*snapshot': 'str',
54
diff --git a/block/rbd.c b/block/rbd.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/rbd.c
57
+++ b/block/rbd.c
58
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRBDState {
59
rbd_image_t image;
60
char *image_name;
61
char *snap;
62
+ char *namespace;
63
uint64_t image_size;
64
} BDRVRBDState;
65
66
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
67
const char *start;
68
char *p, *buf;
69
QList *keypairs = NULL;
70
- char *found_str;
71
+ char *found_str, *image_name;
72
73
if (!strstart(filename, "rbd:", &start)) {
74
error_setg(errp, "File name must start with 'rbd:'");
75
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
76
qdict_put_str(options, "pool", found_str);
77
78
if (strchr(p, '@')) {
79
- found_str = qemu_rbd_next_tok(p, '@', &p);
80
- qemu_rbd_unescape(found_str);
81
- qdict_put_str(options, "image", found_str);
82
+ image_name = qemu_rbd_next_tok(p, '@', &p);
83
84
found_str = qemu_rbd_next_tok(p, ':', &p);
85
qemu_rbd_unescape(found_str);
86
qdict_put_str(options, "snapshot", found_str);
87
} else {
88
- found_str = qemu_rbd_next_tok(p, ':', &p);
89
+ image_name = qemu_rbd_next_tok(p, ':', &p);
90
+ }
91
+ /* Check for namespace in the image_name */
92
+ if (strchr(image_name, '/')) {
93
+ found_str = qemu_rbd_next_tok(image_name, '/', &image_name);
94
qemu_rbd_unescape(found_str);
95
- qdict_put_str(options, "image", found_str);
96
+ qdict_put_str(options, "namespace", found_str);
97
+ } else {
98
+ qdict_put_str(options, "namespace", "");
99
}
100
+ qemu_rbd_unescape(image_name);
101
+ qdict_put_str(options, "image", image_name);
102
if (!p) {
103
goto done;
104
}
105
@@ -XXX,XX +XXX,XX @@ static QemuOptsList runtime_opts = {
106
.type = QEMU_OPT_STRING,
107
.help = "Rados pool name",
108
},
109
+ {
110
+ .name = "namespace",
111
+ .type = QEMU_OPT_STRING,
112
+ .help = "Rados namespace name in the pool",
113
+ },
114
{
115
.name = "image",
116
.type = QEMU_OPT_STRING,
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename,
118
* schema, but when they come from -drive, they're all QString.
119
*/
120
loc = rbd_opts->location;
121
- loc->pool = g_strdup(qdict_get_try_str(options, "pool"));
122
- loc->conf = g_strdup(qdict_get_try_str(options, "conf"));
123
- loc->has_conf = !!loc->conf;
124
- loc->user = g_strdup(qdict_get_try_str(options, "user"));
125
- loc->has_user = !!loc->user;
126
- loc->image = g_strdup(qdict_get_try_str(options, "image"));
127
- keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
128
+ loc->pool = g_strdup(qdict_get_try_str(options, "pool"));
129
+ loc->conf = g_strdup(qdict_get_try_str(options, "conf"));
130
+ loc->has_conf = !!loc->conf;
131
+ loc->user = g_strdup(qdict_get_try_str(options, "user"));
132
+ loc->has_user = !!loc->user;
133
+ loc->q_namespace = g_strdup(qdict_get_try_str(options, "namespace"));
134
+ loc->image = g_strdup(qdict_get_try_str(options, "image"));
135
+ keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
136
137
ret = qemu_rbd_do_create(create_options, keypairs, password_secret, errp);
138
if (ret < 0) {
139
@@ -XXX,XX +XXX,XX @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
140
error_setg_errno(errp, -r, "error opening pool %s", opts->pool);
141
goto failed_shutdown;
142
}
143
+ /*
144
+ * Set the namespace after opening the io context on the pool,
145
+ * if nspace == NULL or if nspace == "", it is just as we did nothing
146
+ */
147
+ rados_ioctx_set_namespace(*io_ctx, opts->q_namespace);
148
149
return 0;
28
150
29
--
151
--
30
2.13.6
152
2.20.1
31
153
32
154
diff view generated by jsdifflib
1
Commit 881cfd17 added a new test binary, include it in .gitignore.
1
We'll want to test more than one successful case in the future, so
2
prepare the test for that by a refactoring that runs each scenario in a
3
separate VM.
2
4
3
Reported-by: Eric Blake <eblake@redhat.com>
5
test_iothreads_switch_{backing,overlay} currently produce errors, but
6
these are cases that should actually work, by switching either the
7
backing file node or the overlay node to the AioContext of the other
8
node.
9
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Tested-by: Peter Krempa <pkrempa@redhat.com>
12
Message-Id: <20200306141413.30705-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
14
---
7
tests/.gitignore | 1 +
15
tests/qemu-iotests/245 | 47 ++++++++++++++++++++++++++++++--------
8
1 file changed, 1 insertion(+)
16
tests/qemu-iotests/245.out | 4 ++--
17
2 files changed, 39 insertions(+), 12 deletions(-)
9
18
10
diff --git a/tests/.gitignore b/tests/.gitignore
19
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
20
index XXXXXXX..XXXXXXX 100755
21
--- a/tests/qemu-iotests/245
22
+++ b/tests/qemu-iotests/245
23
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
24
self.assertEqual(self.get_node('hd1'), None)
25
self.assert_qmp(self.get_node('hd2'), 'ro', True)
26
27
- # We don't allow setting a backing file that uses a different AioContext
28
- def test_iothreads(self):
29
+ def run_test_iothreads(self, iothread_a, iothread_b, errmsg = None):
30
opts = hd_opts(0)
31
result = self.vm.qmp('blockdev-add', conv_keys = False, **opts)
32
self.assert_qmp(result, 'return', {})
33
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
34
result = self.vm.qmp('object-add', qom_type='iothread', id='iothread1')
35
self.assert_qmp(result, 'return', {})
36
37
- result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd0', iothread='iothread0')
38
+ result = self.vm.qmp('device_add', driver='virtio-scsi', id='scsi0',
39
+ iothread=iothread_a)
40
self.assert_qmp(result, 'return', {})
41
42
- self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext")
43
-
44
- result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread1')
45
+ result = self.vm.qmp('device_add', driver='virtio-scsi', id='scsi1',
46
+ iothread=iothread_b)
47
self.assert_qmp(result, 'return', {})
48
49
- self.reopen(opts, {'backing': 'hd2'}, "Cannot use a new backing file with a different AioContext")
50
+ if iothread_a:
51
+ result = self.vm.qmp('device_add', driver='scsi-hd', drive='hd0',
52
+ share_rw=True, bus="scsi0.0")
53
+ self.assert_qmp(result, 'return', {})
54
55
- result = self.vm.qmp('x-blockdev-set-iothread', node_name='hd2', iothread='iothread0')
56
- self.assert_qmp(result, 'return', {})
57
+ if iothread_b:
58
+ result = self.vm.qmp('device_add', driver='scsi-hd', drive='hd2',
59
+ share_rw=True, bus="scsi1.0")
60
+ self.assert_qmp(result, 'return', {})
61
62
- self.reopen(opts, {'backing': 'hd2'})
63
+ # Attaching the backing file may or may not work
64
+ self.reopen(opts, {'backing': 'hd2'}, errmsg)
65
+
66
+ # But removing the backing file should always work
67
+ self.reopen(opts, {'backing': None})
68
+
69
+ self.vm.shutdown()
70
+
71
+ # We don't allow setting a backing file that uses a different AioContext if
72
+ # neither of them can switch to the other AioContext
73
+ def test_iothreads_error(self):
74
+ self.run_test_iothreads('iothread0', 'iothread1',
75
+ "Cannot use a new backing file with a different AioContext")
76
+
77
+ def test_iothreads_compatible_users(self):
78
+ self.run_test_iothreads('iothread0', 'iothread0')
79
+
80
+ def test_iothreads_switch_backing(self):
81
+ self.run_test_iothreads('iothread0', None,
82
+ "Cannot use a new backing file with a different AioContext")
83
+
84
+ def test_iothreads_switch_overlay(self):
85
+ self.run_test_iothreads(None, 'iothread0',
86
+ "Cannot use a new backing file with a different AioContext")
87
88
if __name__ == '__main__':
89
iotests.main(supported_fmts=["qcow2"],
90
diff --git a/tests/qemu-iotests/245.out b/tests/qemu-iotests/245.out
11
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/.gitignore
92
--- a/tests/qemu-iotests/245.out
13
+++ b/tests/.gitignore
93
+++ b/tests/qemu-iotests/245.out
14
@@ -XXX,XX +XXX,XX @@ test-aio
94
@@ -XXX,XX +XXX,XX @@
15
test-aio-multithread
95
-..................
16
test-arm-mptimer
96
+.....................
17
test-base64
97
----------------------------------------------------------------------
18
+test-bdrv-drain
98
-Ran 18 tests
19
test-bitops
99
+Ran 21 tests
20
test-bitcnt
100
21
test-blockjob
101
OK
102
{"execute": "job-finalize", "arguments": {"id": "commit0"}}
22
--
103
--
23
2.13.6
104
2.20.1
24
105
25
106
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
This patch allows bdrv_reopen() (and therefore the x-blockdev-reopen QMP
2
command) to attach a node as the new backing file even if the node is in
3
a different AioContext than the parent if one of both nodes can be moved
4
to the AioContext of the other node.
2
5
3
This is not necessarily complete, but it should include the most
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
important places.
7
Tested-by: Peter Krempa <pkrempa@redhat.com>
8
Message-Id: <20200306141413.30705-3-kwolf@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block.c | 32 ++++++++++++++++++++++++++------
13
tests/qemu-iotests/245 | 8 +++-----
14
2 files changed, 29 insertions(+), 11 deletions(-)
5
15
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
diff --git a/block.c b/block.c
7
Message-id: 20171123020832.8165-4-mreitz@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qcow.c | 16 ++++++++++++++++
12
1 file changed, 16 insertions(+)
13
14
diff --git a/block/qcow.c b/block/qcow.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow.c
18
--- a/block.c
17
+++ b/block/qcow.c
19
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
20
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
19
/* update the L1 entry */
21
*shared = cumulative_shared_perms;
20
s->l1_table[l1_index] = l2_offset;
22
}
21
tmp = cpu_to_be64(l2_offset);
23
22
+ BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
24
+static bool bdrv_reopen_can_attach(BlockDriverState *parent,
23
ret = bdrv_pwrite_sync(bs->file,
25
+ BdrvChild *child,
24
s->l1_table_offset + l1_index * sizeof(tmp),
26
+ BlockDriverState *new_child,
25
&tmp, sizeof(tmp));
27
+ Error **errp)
26
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
28
+{
29
+ AioContext *parent_ctx = bdrv_get_aio_context(parent);
30
+ AioContext *child_ctx = bdrv_get_aio_context(new_child);
31
+ GSList *ignore;
32
+ bool ret;
33
+
34
+ ignore = g_slist_prepend(NULL, child);
35
+ ret = bdrv_can_set_aio_context(new_child, parent_ctx, &ignore, NULL);
36
+ g_slist_free(ignore);
37
+ if (ret) {
38
+ return ret;
39
+ }
40
+
41
+ ignore = g_slist_prepend(NULL, child);
42
+ ret = bdrv_can_set_aio_context(parent, child_ctx, &ignore, errp);
43
+ g_slist_free(ignore);
44
+ return ret;
45
+}
46
+
47
/*
48
* Take a BDRVReopenState and check if the value of 'backing' in the
49
* reopen_state->options QDict is valid or not.
50
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
51
}
52
53
/*
54
- * TODO: before removing the x- prefix from x-blockdev-reopen we
55
- * should move the new backing file into the right AioContext
56
- * instead of returning an error.
57
+ * Check AioContext compatibility so that the bdrv_set_backing_hd() call in
58
+ * bdrv_reopen_commit() won't fail.
59
*/
60
if (new_backing_bs) {
61
- if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) {
62
- error_setg(errp, "Cannot use a new backing file "
63
- "with a different AioContext");
64
+ if (!bdrv_reopen_can_attach(bs, bs->backing, new_backing_bs, errp)) {
65
return -EINVAL;
27
}
66
}
28
}
67
}
29
l2_table = s->l2_cache + (min_index << s->l2_bits);
68
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
30
+ BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
69
index XXXXXXX..XXXXXXX 100755
31
if (new_l2_table) {
70
--- a/tests/qemu-iotests/245
32
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
71
+++ b/tests/qemu-iotests/245
33
ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
72
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
34
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
73
# neither of them can switch to the other AioContext
35
((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
74
def test_iothreads_error(self):
36
if (!allocate)
75
self.run_test_iothreads('iothread0', 'iothread1',
37
return 0;
76
- "Cannot use a new backing file with a different AioContext")
38
+ BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
77
+ "Cannot change iothread of active block backend")
39
/* allocate a new cluster */
78
40
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
79
def test_iothreads_compatible_users(self):
41
(n_end - n_start) < s->cluster_sectors) {
80
self.run_test_iothreads('iothread0', 'iothread0')
42
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
81
43
}
82
def test_iothreads_switch_backing(self):
44
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
83
- self.run_test_iothreads('iothread0', None,
45
/* write the cluster content */
84
- "Cannot use a new backing file with a different AioContext")
46
+ BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
85
+ self.run_test_iothreads('iothread0', None)
47
ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
86
48
s->cluster_size);
87
def test_iothreads_switch_overlay(self):
49
if (ret < 0) {
88
- self.run_test_iothreads(None, 'iothread0',
50
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
89
- "Cannot use a new backing file with a different AioContext")
51
NULL) < 0) {
90
+ self.run_test_iothreads(None, 'iothread0')
52
return -EIO;
91
53
}
92
if __name__ == '__main__':
54
+ BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
93
iotests.main(supported_fmts=["qcow2"],
55
ret = bdrv_pwrite(bs->file,
56
cluster_offset + i * 512,
57
s->cluster_data, 512);
58
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
59
/* update L2 table */
60
tmp = cpu_to_be64(cluster_offset);
61
l2_table[l2_index] = tmp;
62
+ if (allocate == 2) {
63
+ BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
64
+ } else {
65
+ BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
66
+ }
67
ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
68
&tmp, sizeof(tmp));
69
if (ret < 0) {
70
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
71
if (s->cluster_cache_offset != coffset) {
72
csize = cluster_offset >> (63 - s->cluster_bits);
73
csize &= (s->cluster_size - 1);
74
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
75
ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
76
if (ret != csize)
77
return -1;
78
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
79
hd_iov.iov_len = n * 512;
80
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
81
qemu_co_mutex_unlock(&s->lock);
82
+ /* qcow2 emits this on bs->file instead of bs->backing */
83
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
84
ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
85
qemu_co_mutex_lock(&s->lock);
86
if (ret < 0) {
87
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
88
hd_iov.iov_len = n * 512;
89
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
90
qemu_co_mutex_unlock(&s->lock);
91
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
92
ret = bdrv_co_readv(bs->file,
93
(cluster_offset >> 9) + index_in_cluster,
94
n, &hd_qiov);
95
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
96
hd_iov.iov_len = n * 512;
97
qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);
98
qemu_co_mutex_unlock(&s->lock);
99
+ BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
100
ret = bdrv_co_writev(bs->file,
101
(cluster_offset >> 9) + index_in_cluster,
102
n, &hd_qiov);
103
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
104
.iov_len = out_len,
105
};
106
qemu_iovec_init_external(&hd_qiov, &iov, 1);
107
+ BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
108
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
109
if (ret < 0) {
110
goto fail;
111
--
94
--
112
2.13.6
95
2.20.1
113
96
114
97
diff view generated by jsdifflib