1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
1
The following changes since commit f4c4357fbfca0fb14e477bf661ae7384b4b9b283:
2
2
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
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 eaae29ef89d498d0eac553c77b554f310a47f809:
9
for you to fetch changes up to 1de6b45fb5c1489b450df7d1a4c692bba9678ce6:
10
10
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
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
15
16
- Fix resize (extending) of short overlays
16
- Add qemu-storage-daemon (still experimental)
17
- nvme: introduce PMR support from NVMe 1.4 spec
17
- rbd: Add support for ceph namespaces
18
- qemu-storage-daemon: Fix non-string --object properties
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
19
21
20
----------------------------------------------------------------
22
----------------------------------------------------------------
21
Alberto Garcia (1):
23
Florian Florensa (1):
22
qcow2: Add incompatibility note between backing files and raw external data files
24
block/rbd: Add support for ceph namespaces
23
25
24
Andrzej Jakowski (1):
26
Kevin Wolf (22):
25
nvme: introduce PMR support from NVMe 1.4 spec
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
26
49
27
Kevin Wolf (12):
50
Max Reitz (4):
28
block: Add flags to BlockDriver.bdrv_co_truncate()
51
qcow2: Fix alloc_cluster_abort() for pre-existing clusters
29
block: Add flags to bdrv(_co)_truncate()
52
iotests/026: Test EIO on preallocated zero cluster
30
block-backend: Add flags to blk_truncate()
53
iotests/026: Test EIO on allocation in a data-file
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
54
block: Fix leak in bdrv_create_file_fallback()
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: truncate: Don't make backing file data visible
35
iotests: Filter testfiles out in filter_img_info()
36
iotests: Test committing to short backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
40
55
41
Paolo Bonzini (1):
56
Peter Krempa (2):
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
57
block: Introduce 'bdrv_reopen_commit_post' step
58
block/qcow2: Move bitmap reopen into bdrv_reopen_commit_post
43
59
44
docs/interop/qcow2.txt | 3 +
60
qapi/block-core.json | 733 +++++++++++++++++------------------
45
hw/block/nvme.h | 2 +
61
qapi/block.json | 512 ++++++++++++++----------
46
include/block/block.h | 5 +-
62
qapi/control.json | 37 ++
47
include/block/block_int.h | 10 +-
63
qapi/pragma.json | 24 ++
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
64
qapi/qapi-schema.json | 25 +-
49
include/qom/object_interfaces.h | 16 +++
65
qapi/qom.json | 12 +-
50
include/sysemu/block-backend.h | 2 +-
66
qapi/transaction.json | 2 +-
51
block.c | 3 +-
67
docs/system/deprecated.rst | 5 +
52
block/block-backend.c | 4 +-
68
configure | 2 +-
53
block/commit.c | 4 +-
69
include/block/block_int.h | 1 +
54
block/crypto.c | 7 +-
70
include/block/nbd.h | 1 +
55
block/file-posix.c | 6 +-
71
include/monitor/monitor.h | 6 +-
56
block/file-win32.c | 2 +-
72
include/qom/object_interfaces.h | 7 +
57
block/gluster.c | 1 +
73
include/sysemu/arch_init.h | 2 +
58
block/io.c | 43 ++++++-
74
block.c | 44 ++-
59
block/iscsi.c | 2 +-
75
block/qapi-sysemu.c | 590 ++++++++++++++++++++++++++++
60
block/mirror.c | 2 +-
76
block/qcow2-cluster.c | 2 +-
61
block/nfs.c | 3 +-
77
block/qcow2.c | 7 +-
62
block/parallels.c | 6 +-
78
block/rbd.c | 44 ++-
63
block/qcow.c | 4 +-
79
blockdev-nbd.c | 40 +-
64
block/qcow2-cluster.c | 2 +-
80
blockdev.c | 559 --------------------------
65
block/qcow2-refcount.c | 2 +-
81
chardev/char.c | 8 +-
66
block/qcow2.c | 73 +++++++++--
82
gdbstub.c | 2 +-
67
block/qed.c | 3 +-
83
hw/block/xen-block.c | 11 +-
68
block/raw-format.c | 6 +-
84
monitor/hmp-cmds.c | 21 +-
69
block/rbd.c | 1 +
85
monitor/hmp.c | 8 +-
70
block/sheepdog.c | 4 +-
86
monitor/misc.c | 2 +
71
block/ssh.c | 2 +-
87
monitor/monitor.c | 86 ++--
72
block/vdi.c | 2 +-
88
monitor/qmp-cmds.c | 2 +-
73
block/vhdx-log.c | 2 +-
89
monitor/qmp.c | 11 +-
74
block/vhdx.c | 6 +-
90
qemu-storage-daemon.c | 340 ++++++++++++++++
75
block/vmdk.c | 8 +-
91
qom/qom-qmp-cmds.c | 42 +-
76
block/vpc.c | 2 +-
92
stubs/arch_type.c | 4 +
77
blockdev.c | 2 +-
93
stubs/monitor-core.c | 21 +
78
hw/block/nvme.c | 109 ++++++++++++++++
94
stubs/monitor.c | 17 +-
79
qemu-img.c | 2 +-
95
tests/test-util-sockets.c | 4 +-
80
qemu-io-cmds.c | 2 +-
96
scripts/qapi/gen.py | 5 +
81
qemu-storage-daemon.c | 4 +-
97
Makefile | 37 ++
82
qom/object_interfaces.c | 31 +++++
98
Makefile.objs | 9 +
83
qom/qom-qmp-cmds.c | 24 +---
99
block/Makefile.objs | 4 +-
84
tests/test-block-iothread.c | 9 +-
100
monitor/Makefile.objs | 2 +
85
tests/qemu-iotests/iotests.py | 5 +-
101
qapi/Makefile.objs | 7 +-
86
hw/block/Makefile.objs | 2 +-
102
qom/Makefile.objs | 1 +
87
hw/block/trace-events | 4 +
103
storage-daemon/Makefile.objs | 1 +
88
tests/qemu-iotests/244 | 10 +-
104
storage-daemon/qapi/Makefile.objs | 1 +
89
tests/qemu-iotests/244.out | 9 +-
105
storage-daemon/qapi/qapi-schema.json | 26 ++
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
106
stubs/Makefile.objs | 2 +
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
107
tests/qemu-iotests/026 | 53 +++
92
tests/qemu-iotests/group | 1 +
108
tests/qemu-iotests/026.out | 16 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
109
tests/qemu-iotests/026.out.nocache | 16 +
94
create mode 100755 tests/qemu-iotests/274
110
tests/qemu-iotests/245 | 45 ++-
95
create mode 100644 tests/qemu-iotests/274.out
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
96
121
97
122
diff view generated by jsdifflib
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
1
From: Max Reitz <mreitz@redhat.com>
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
3
undo any previous preallocation, but just adds the zero flag to all
4
relevant L2 entries. If an external data file is in use, a write_zeroes
5
request to the data file is made instead.
6
2
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
handle_alloc() reuses preallocated zero clusters. If anything goes
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
4
wrong during the data write, we do not change their L2 entry, so we
9
Reviewed-by: Eric Blake <eblake@redhat.com>
5
must not let qcow2_alloc_cluster_abort() free them.
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
7
Fixes: 8b24cd141549b5b264baeddd4e72902cfb5de23b
8
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20200225143130.111267-2-mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
12
---
13
block/qcow2-cluster.c | 2 +-
13
block/qcow2-cluster.c | 2 +-
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
2 files changed, 35 insertions(+), 1 deletion(-)
16
15
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
16
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
18
--- a/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
19
+++ b/block/qcow2-cluster.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
20
@@ -XXX,XX +XXX,XX @@ err:
22
/* Caller must pass aligned values, except at image end */
21
void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
22
{
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
23
BDRVQcow2State *s = bs->opaque;
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
24
- if (!has_data_file(bs)) {
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
25
+ if (!has_data_file(bs) && !m->keep_old_clusters) {
27
26
qcow2_free_clusters(bs, m->alloc_offset,
28
/* The zero flag is only supported by version 3 and newer */
27
m->nb_clusters << s->cluster_bits,
29
if (s->qcow_version < 3) {
28
QCOW2_DISCARD_NEVER);
30
diff --git a/block/qcow2.c b/block/qcow2.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
44
}
45
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
48
+
49
+ /*
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
52
+ * at the end of the image (which it is here).
53
+ */
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
55
+ if (ret < 0) {
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
57
+ goto fail;
58
+ }
59
+
60
+ /* Write explicit zeros for the unaligned head */
61
+ if (zero_start > old_length) {
62
+ uint64_t len = zero_start - old_length;
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
64
+ QEMUIOVector qiov;
65
+ qemu_iovec_init_buf(&qiov, buf, len);
66
+
67
+ qemu_co_mutex_unlock(&s->lock);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
69
+ qemu_co_mutex_lock(&s->lock);
70
+
71
+ qemu_vfree(buf);
72
+ if (ret < 0) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
82
--
29
--
83
2.25.3
30
2.20.1
84
31
85
32
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Test what happens when writing data to a preallocated zero cluster, but
4
the data write fails.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20200225143130.111267-3-mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
tests/qemu-iotests/026 | 21 +++++++++++++++++++++
11
tests/qemu-iotests/026.out | 10 ++++++++++
12
tests/qemu-iotests/026.out.nocache | 10 ++++++++++
13
3 files changed, 41 insertions(+)
14
15
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/026
18
+++ b/tests/qemu-iotests/026
19
@@ -XXX,XX +XXX,XX @@ _make_test_img 64M
20
$QEMU_IO -c "write 0 1M" -c "write 0 1M" "$BLKDBG_TEST_IMG" | _filter_qemu_io
21
_check_test_img
22
23
+echo
24
+echo === Avoid freeing preallocated zero clusters on failure ===
25
+echo
26
+
27
+cat > "$TEST_DIR/blkdebug.conf" <<EOF
28
+[inject-error]
29
+event = "write_aio"
30
+errno = "5"
31
+once = "on"
32
+EOF
33
+
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
+
44
# success, all done
45
echo "*** done"
46
rm -f $seq.full
47
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
48
index XXXXXXX..XXXXXXX 100644
49
--- a/tests/qemu-iotests/026.out
50
+++ b/tests/qemu-iotests/026.out
51
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
52
wrote 1048576/1048576 bytes at offset 0
53
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
54
No errors were found on the image.
55
+
56
+=== Avoid freeing preallocated zero clusters on failure ===
57
+
58
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
59
+wrote 1024/1024 bytes at offset 0
60
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
61
+wrote 1024/1024 bytes at offset 0
62
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
+write failed: Input/output error
64
+No errors were found on the image.
65
*** done
66
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
67
index XXXXXXX..XXXXXXX 100644
68
--- a/tests/qemu-iotests/026.out.nocache
69
+++ b/tests/qemu-iotests/026.out.nocache
70
@@ -XXX,XX +XXX,XX @@ write failed: Input/output error
71
wrote 1048576/1048576 bytes at offset 0
72
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
No errors were found on the image.
74
+
75
+=== Avoid freeing preallocated zero clusters on failure ===
76
+
77
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024
78
+wrote 1024/1024 bytes at offset 0
79
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
80
+wrote 1024/1024 bytes at offset 0
81
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
82
+write failed: Input/output error
83
+No errors were found on the image.
84
*** done
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
Test what happens when writing data to an external data file, where the
4
write requires an L2 entry to be allocated, but the data write fails.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20200225143130.111267-4-mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
tests/qemu-iotests/026 | 32 ++++++++++++++++++++++++++++++
11
tests/qemu-iotests/026.out | 6 ++++++
12
tests/qemu-iotests/026.out.nocache | 6 ++++++
13
3 files changed, 44 insertions(+)
14
15
diff --git a/tests/qemu-iotests/026 b/tests/qemu-iotests/026
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/026
18
+++ b/tests/qemu-iotests/026
19
@@ -XXX,XX +XXX,XX @@ _cleanup()
20
{
21
    _cleanup_test_img
22
rm "$TEST_DIR/blkdebug.conf"
23
+ rm -f "$TEST_IMG.data_file"
24
}
25
trap "_cleanup; exit \$status" 0 1 2 3 15
26
27
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write 0 $CLUSTER_SIZE" "$BLKDBG_TEST_IMG" | _filter_qemu_io
28
29
_check_test_img
30
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
+
62
# success, all done
63
echo "*** done"
64
rm -f $seq.full
65
diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out
66
index XXXXXXX..XXXXXXX 100644
67
--- a/tests/qemu-iotests/026.out
68
+++ b/tests/qemu-iotests/026.out
69
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 0
70
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
write failed: Input/output error
72
No errors were found on the image.
73
+
74
+=== Avoid freeing external data clusters on failure ===
75
+
76
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1024 data_file=TEST_DIR/t.IMGFMT.data_file
77
+write failed: Input/output error
78
+No errors were found on the image.
79
*** done
80
diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache
81
index XXXXXXX..XXXXXXX 100644
82
--- a/tests/qemu-iotests/026.out.nocache
83
+++ b/tests/qemu-iotests/026.out.nocache
84
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 0
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.
94
*** done
95
--
96
2.20.1
97
98
diff view generated by jsdifflib
New patch
1
From: Max Reitz <mreitz@redhat.com>
1
2
3
@options is leaked by the first two return statements in this function.
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")
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20200225155618.133412-1-mreitz@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block.c | 3 ++-
17
1 file changed, 2 insertions(+), 1 deletion(-)
18
19
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
22
+++ b/block.c
23
@@ -XXX,XX +XXX,XX @@ static int bdrv_create_file_fallback(const char *filename, BlockDriver *drv,
24
QemuOpts *opts, Error **errp)
25
{
26
BlockBackend *blk;
27
- QDict *options = qdict_new();
28
+ QDict *options;
29
int64_t size = 0;
30
char *buf = NULL;
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,
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
1
From: Peter Krempa <pkrempa@redhat.com>
2
driver callbacks, and a supported_truncate_flags field in
3
BlockDriverState that allows drivers to advertise support for request
4
flags in the context of truncate.
5
2
6
For now, we always pass 0 and no drivers declare support for any flag.
3
Add another step in the reopen process where driver can execute code
4
after permission changes are comitted.
7
5
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Message-Id: <adc02cf591c3cb34e98e33518eb1c540a0f27db1.1582893284.git.pkrempa@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
9
---
15
include/block/block_int.h | 10 +++++++++-
10
include/block/block_int.h | 1 +
16
block/crypto.c | 3 ++-
11
block.c | 9 +++++++++
17
block/file-posix.c | 2 +-
12
2 files changed, 10 insertions(+)
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
20
block/io.c | 8 +++++++-
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
31
13
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
16
--- a/include/block/block_int.h
35
+++ b/include/block/block_int.h
17
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
*/
19
int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
20
BlockReopenQueue *queue, Error **errp);
39
bool exact, PreallocMode prealloc,
21
void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
40
- Error **errp);
22
+ void (*bdrv_reopen_commit_post)(BDRVReopenState *reopen_state);
41
+ BdrvRequestFlags flags, Error **errp);
23
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
42
24
void (*bdrv_join_options)(QDict *options, QDict *old_options);
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
25
44
bool has_variable_length;
26
diff --git a/block.c b/block.c
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
28
--- a/block.c
63
+++ b/block/crypto.c
29
+++ b/block.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
30
@@ -XXX,XX +XXX,XX @@ cleanup_perm:
65
31
}
66
static int coroutine_fn
32
}
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
68
- PreallocMode prealloc, Error **errp)
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
70
+ Error **errp)
71
{
72
BlockCrypto *crypto = bs->opaque;
73
uint64_t payload_offset =
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
33
}
126
34
+
127
if (drv->bdrv_co_truncate) {
35
+ if (ret == 0) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
36
+ QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) {
129
+ if (flags & ~bs->supported_truncate_flags) {
37
+ BlockDriverState *bs = bs_entry->state.bs;
130
+ error_setg(errp, "Block driver does not support requested flags");
38
+
131
+ ret = -ENOTSUP;
39
+ if (bs->drv->bdrv_reopen_commit_post)
132
+ goto out;
40
+ bs->drv->bdrv_reopen_commit_post(&bs_entry->state);
133
+ }
41
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
42
+ }
135
} else if (bs->file && drv->is_filter) {
43
cleanup:
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
44
QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) {
137
} else {
45
if (ret) {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
264
--
46
--
265
2.25.3
47
2.20.1
266
48
267
49
diff view generated by jsdifflib
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
1
From: Peter Krempa <pkrempa@redhat.com>
2
image is possibly preallocated and then the zero flag is added to all
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
6
2
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
3
The bitmap code requires writing the 'file' child when the qcow2 driver
8
and if the protocol driver can ensure that the new area reads as zeros,
4
is reopened in read-write mode.
9
we can skip setting the zero flag in the qcow2 layer.
10
5
11
Unfortunately, the same approach doesn't work for metadata
6
If the 'file' child is being reopened due to a permissions change, the
12
preallocation, so we'll still set the zero flag there.
7
modification is commited yet when qcow2_reopen_commit is called. This
8
means that any attempt to write the 'file' child will end with EBADFD
9
as the original fd was already closed.
13
10
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Moving bitmap reopening to the new callback which is called after
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
permission modifications are commited fixes this as the file descriptor
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
13
will be replaced with the correct one.
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
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>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
22
---
20
block/qcow2.c | 22 +++++++++++++++++++---
23
block/qcow2.c | 7 ++++++-
21
tests/qemu-iotests/274.out | 4 ++--
24
1 file changed, 6 insertions(+), 1 deletion(-)
22
2 files changed, 21 insertions(+), 5 deletions(-)
23
25
24
diff --git a/block/qcow2.c b/block/qcow2.c
26
diff --git a/block/qcow2.c b/block/qcow2.c
25
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.c
28
--- a/block/qcow2.c
27
+++ b/block/qcow2.c
29
+++ b/block/qcow2.c
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
30
@@ -XXX,XX +XXX,XX @@ fail:
29
/* Allocate the data area */
31
static void qcow2_reopen_commit(BDRVReopenState *state)
30
new_file_size = allocation_start +
32
{
31
nb_new_data_clusters * s->cluster_size;
33
qcow2_update_options_commit(state->bs, state->opaque);
32
- /* Image file grows, so @exact does not matter */
34
+ g_free(state->opaque);
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
35
+}
34
- errp);
36
+
35
+ /*
37
+static void qcow2_reopen_commit_post(BDRVReopenState *state)
36
+ * Image file grows, so @exact does not matter.
38
+{
37
+ *
39
if (state->flags & BDRV_O_RDWR) {
38
+ * If we need to zero out the new area, try first whether the protocol
40
Error *local_err = NULL;
39
+ * driver can already take care of this.
41
40
+ */
42
@@ -XXX,XX +XXX,XX @@ static void qcow2_reopen_commit(BDRVReopenState *state)
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
43
bdrv_get_node_name(state->bs));
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
44
}
43
+ BDRV_REQ_ZERO_WRITE, NULL);
45
}
44
+ if (ret >= 0) {
46
- g_free(state->opaque);
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
47
}
46
+ }
48
47
+ } else {
49
static void qcow2_reopen_abort(BDRVReopenState *state)
48
+ ret = -1;
50
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_qcow2 = {
49
+ }
51
.bdrv_close = qcow2_close,
50
+ if (ret < 0) {
52
.bdrv_reopen_prepare = qcow2_reopen_prepare,
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
53
.bdrv_reopen_commit = qcow2_reopen_commit,
52
+ errp);
54
+ .bdrv_reopen_commit_post = qcow2_reopen_commit_post,
53
+ }
55
.bdrv_reopen_abort = qcow2_reopen_abort,
54
if (ret < 0) {
56
.bdrv_join_options = qcow2_join_options,
55
error_prepend(errp, "Failed to resize underlying file: ");
57
.bdrv_child_perm = bdrv_format_default_perms,
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/274.out
60
+++ b/tests/qemu-iotests/274.out
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
63
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
79
--
58
--
80
2.25.3
59
2.20.1
81
60
82
61
diff view generated by jsdifflib
New patch
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.
1
4
5
Even though this doesn't add any options yet that create things (like
6
--object or --blockdev), already document that we're planning to process
7
them in the order they are given on the command line rather than trying
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>
15
---
16
configure | 2 +-
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
21
22
diff --git a/configure b/configure
23
index XXXXXXX..XXXXXXX 100755
24
--- a/configure
25
+++ b/configure
26
@@ -XXX,XX +XXX,XX @@ tools=""
27
if test "$want_tools" = "yes" ; then
28
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) qemu-edid\$(EXESUF) $tools"
29
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
30
- tools="qemu-nbd\$(EXESUF) $tools"
31
+ tools="qemu-nbd\$(EXESUF) qemu-storage-daemon\$(EXESUF) $tools"
32
fi
33
if [ "$ivshmem" = "yes" ]; then
34
tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
35
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
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
180
--
181
2.20.1
182
183
diff view generated by jsdifflib
New patch
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.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20200224143008.13362-3-kwolf@redhat.com>
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
15
16
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/arch_init.h
19
+++ b/include/sysemu/arch_init.h
20
@@ -XXX,XX +XXX,XX @@ enum {
21
QEMU_ARCH_NIOS2 = (1 << 17),
22
QEMU_ARCH_HPPA = (1 << 18),
23
QEMU_ARCH_RISCV = (1 << 19),
24
+
25
+ QEMU_ARCH_NONE = (1 << 31),
26
};
27
28
extern const uint32_t arch_type;
29
diff --git a/stubs/arch_type.c b/stubs/arch_type.c
30
new file mode 100644
31
index XXXXXXX..XXXXXXX
32
--- /dev/null
33
+++ b/stubs/arch_type.c
34
@@ -XXX,XX +XXX,XX @@
35
+#include "qemu/osdep.h"
36
+#include "sysemu/arch_init.h"
37
+
38
+const uint32_t arch_type = QEMU_ARCH_NONE;
39
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
40
index XXXXXXX..XXXXXXX 100644
41
--- a/stubs/Makefile.objs
42
+++ b/stubs/Makefile.objs
43
@@ -XXX,XX +XXX,XX @@
44
+stub-obj-y += arch_type.o
45
stub-obj-y += bdrv-next-monitor-owned.o
46
stub-obj-y += blk-commit-all.o
47
stub-obj-y += blockdev-close-all-bdrv-states.o
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
New patch
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.
1
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Message-Id: <20200224143008.13362-4-kwolf@redhat.com>
8
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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
16
17
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/block/qapi-sysemu.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QMP command handlers specific to the system emulators
25
+ *
26
+ * Copyright (c) 2003-2008 Fabrice Bellard
27
+ *
28
+ * This work is licensed under the terms of the GNU GPL, version 2 or
29
+ * later. See the COPYING file in the top-level directory.
30
+ *
31
+ * This file incorporates work covered by the following copyright and
32
+ * permission notice:
33
+ *
34
+ * Copyright (c) 2003-2008 Fabrice Bellard
35
+ *
36
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ * of this software and associated documentation files (the "Software"), to deal
38
+ * in the Software without restriction, including without limitation the rights
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
614
index XXXXXXX..XXXXXXX 100644
615
--- a/blockdev.c
616
+++ b/blockdev.c
617
@@ -XXX,XX +XXX,XX @@
618
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
619
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
620
621
-static int do_open_tray(const char *blk_name, const char *qdev_id,
622
- bool force, Error **errp);
623
-static void blockdev_remove_medium(bool has_device, const char *device,
624
- bool has_id, const char *id, Error **errp);
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
1212
index XXXXXXX..XXXXXXX 100644
1213
--- a/block/Makefile.objs
1214
+++ b/block/Makefile.objs
1215
@@ -XXX,XX +XXX,XX @@ block-obj-y += filter-compress.o
1216
1217
common-obj-y += stream.o
1218
1219
+common-obj-y += qapi-sysemu.o
1220
+
1221
nfs.o-libs := $(LIBNFS_LIBS)
1222
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
1223
iscsi.o-libs := $(LIBISCSI_LIBS)
1224
--
1225
2.20.1
1226
1227
diff view generated by jsdifflib
New patch
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.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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(-)
13
14
diff --git a/qapi/block-core.json b/qapi/block-core.json
15
index XXXXXXX..XXXXXXX 100644
16
--- a/qapi/block-core.json
17
+++ b/qapi/block-core.json
18
@@ -XXX,XX +XXX,XX @@
19
'data' : { 'node-name': 'str',
20
'iothread': 'StrOrNull',
21
'*force': 'bool' } }
22
+
23
+##
24
+# @nbd-server-start:
25
+#
26
+# Start an NBD server listening on the given host and port. Block
27
+# devices can then be exported using @nbd-server-add. The NBD
28
+# server will present them as named exports; for example, another
29
+# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
30
+#
31
+# @addr: Address on which to listen.
32
+# @tls-creds: ID of the TLS credentials object (since 2.6).
33
+# @tls-authz: ID of the QAuthZ authorization object used to validate
34
+# the client's x509 distinguished name. This object is
35
+# is only resolved at time of use, so can be deleted and
36
+# recreated on the fly while the NBD server is active.
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' } }
618
--
619
2.20.1
620
621
diff view generated by jsdifflib
New patch
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.
1
4
5
The associated data types are actually also used in code shared with the
6
tools, so they stay in block-core.json.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20200224143008.13362-6-kwolf@redhat.com>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
qapi/block-core.json | 386 -------------------------------------------
14
qapi/block.json | 386 +++++++++++++++++++++++++++++++++++++++++++
15
monitor/qmp-cmds.c | 2 +-
16
3 files changed, 387 insertions(+), 387 deletions(-)
17
18
diff --git a/qapi/block-core.json b/qapi/block-core.json
19
index XXXXXXX..XXXXXXX 100644
20
--- a/qapi/block-core.json
21
+++ b/qapi/block-core.json
22
@@ -XXX,XX +XXX,XX @@
23
{ 'struct': 'BlockLatencyHistogramInfo',
24
'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
25
26
-##
27
-# @block-latency-histogram-set:
28
-#
29
-# Manage read, write and flush latency histograms for the device.
30
-#
31
-# If only @id parameter is specified, remove all present latency histograms
32
-# for the device. Otherwise, add/reset some of (or all) latency histograms.
33
-#
34
-# @id: The name or QOM path of the guest device.
35
-#
36
-# @boundaries: list of interval boundary values (see description in
37
-# BlockLatencyHistogramInfo definition). If specified, all
38
-# latency histograms are removed, and empty ones created for all
39
-# io types with intervals corresponding to @boundaries (except for
40
-# io types, for which specific boundaries are set through the
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"
843
--
844
2.20.1
845
846
diff view generated by jsdifflib
New patch
1
This adds a --blockdev option to the storage daemon that works the same
2
as the -blockdev option of the system emulator.
1
3
4
In order to be able to link with blockdev.o, we also need to change
5
stream.o from common-obj to block-obj, which is where all other block
6
jobs already are.
7
8
In contrast to the system emulator, qemu-storage-daemon options will be
9
processed in the order they are given. The user needs to take care to
10
refer to other objects only after defining them.
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>
16
---
17
qemu-storage-daemon.c | 31 +++++++++++++++++++++++++++++++
18
Makefile | 5 ++++-
19
Makefile.objs | 7 +++++++
20
block/Makefile.objs | 2 +-
21
4 files changed, 43 insertions(+), 2 deletions(-)
22
23
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/qemu-storage-daemon.c
26
+++ b/qemu-storage-daemon.c
27
@@ -XXX,XX +XXX,XX @@
28
#include "crypto/init.h"
29
30
#include "qapi/error.h"
31
+#include "qapi/qapi-visit-block-core.h"
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[])
58
{
59
int c;
60
61
static const struct option long_options[] = {
62
+ {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
63
{"help", no_argument, NULL, 'h'},
64
{"trace", required_argument, NULL, 'T'},
65
{"version", no_argument, NULL, 'V'},
66
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
67
printf("qemu-storage-daemon version "
68
QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
69
exit(EXIT_SUCCESS);
70
+ case OPTION_BLOCKDEV:
71
+ {
72
+ Visitor *v;
73
+ BlockdevOptions *options;
74
+
75
+ v = qobject_input_visitor_new_str(optarg, "driver",
76
+ &error_fatal);
77
+
78
+ visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
79
+ visit_free(v);
80
+
81
+ qmp_blockdev_add(options, &error_fatal);
82
+ qapi_free_BlockdevOptions(options);
83
+ break;
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)
129
+
130
+storage-daemon-obj-y = block/
131
+storage-daemon-obj-y += blockdev.o iothread.o
132
+
133
######################################################################
134
# Target independent part of system emulation. The long term path is to
135
# suppress *all* target specific code in case of system emulation, i.e. a
136
diff --git a/block/Makefile.objs b/block/Makefile.objs
137
index XXXXXXX..XXXXXXX 100644
138
--- a/block/Makefile.objs
139
+++ b/block/Makefile.objs
140
@@ -XXX,XX +XXX,XX @@ block-obj-y += aio_task.o
141
block-obj-y += backup-top.o
142
block-obj-y += filter-compress.o
143
144
-common-obj-y += stream.o
145
+block-obj-y += stream.o
146
147
common-obj-y += qapi-sysemu.o
148
149
--
150
2.20.1
151
152
diff view generated by jsdifflib
1
The QMP handler qmp_object_add() and the implementation of --object in
1
Mapping object-add to the command line as is doesn't result in nice
2
qemu-storage-daemon can share most of the code. Currently,
2
syntax because of the nesting introduced with 'props'. This becomes
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
3
nicer and more consistent with device_add and netdev_add when we accept
4
because different visitors need to be used.
4
properties for the object on the top level instead.
5
5
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
6
'props' is still accepted after this patch, but marked as deprecated.
7
new function user_creatable_add_dict() that can get an additional
7
8
parameter. The handling of "props" is only required for compatibility
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
and not required for the qemu-storage-daemon command line, so it stays
9
Message-Id: <20200224143008.13362-8-kwolf@redhat.com>
10
in qmp_object_add().
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
include/qom/object_interfaces.h | 12 ++++++++++++
13
qapi/qom.json | 12 +++++++---
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
14
docs/system/deprecated.rst | 5 ++++
16
qom/qom-qmp-cmds.c | 24 +-----------------------
15
include/qom/object_interfaces.h | 7 ++++++
17
3 files changed, 40 insertions(+), 23 deletions(-)
16
hw/block/xen-block.c | 11 ++++++++-
18
17
monitor/misc.c | 2 ++
18
qom/qom-qmp-cmds.c | 42 +++++++++++++++++++++++++++------
19
6 files changed, 68 insertions(+), 11 deletions(-)
20
21
diff --git a/qapi/qom.json b/qapi/qom.json
22
index XXXXXXX..XXXXXXX 100644
23
--- a/qapi/qom.json
24
+++ b/qapi/qom.json
25
@@ -XXX,XX +XXX,XX @@
26
#
27
# @id: the name of the new object
28
#
29
-# @props: a dictionary of properties to be passed to the backend
30
+# @props: a dictionary of properties to be passed to the backend. Deprecated
31
+# since 5.0, specify the properties on the top level instead. It is an
32
+# error to specify the same option both on the top level and in @props.
33
+#
34
+# Additional arguments depend on qom-type and are passed to the backend
35
+# unchanged.
36
#
37
# Returns: Nothing on success
38
# Error if @qom-type is not a valid class name
39
@@ -XXX,XX +XXX,XX @@
40
#
41
# -> { "execute": "object-add",
42
# "arguments": { "qom-type": "rng-random", "id": "rng1",
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
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
71
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
20
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qom/object_interfaces.h
73
--- a/include/qom/object_interfaces.h
22
+++ b/include/qom/object_interfaces.h
74
+++ b/include/qom/object_interfaces.h
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
75
@@ -XXX,XX +XXX,XX @@ void user_creatable_del(const char *id, Error **errp);
24
const QDict *qdict,
76
*/
25
Visitor *v, Error **errp);
77
void user_creatable_cleanup(void);
26
78
27
+/**
79
+/**
28
+ * user_creatable_add_dict:
80
+ * qmp_object_add:
29
+ * @qdict: the object definition
30
+ * @errp: if an error occurs, a pointer to an area to store the error
31
+ *
81
+ *
32
+ * Create an instance of the user creatable object that is defined by
82
+ * QMP command handler for object-add. See the QAPI schema for documentation.
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
35
+ * initialize the object properties.
36
+ */
83
+ */
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
84
+void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp);
38
+
85
+
39
/**
86
#endif
40
* user_creatable_add_opts:
87
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
41
* @opts: the object definition
88
index XXXXXXX..XXXXXXX 100644
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
89
--- a/hw/block/xen-block.c
43
index XXXXXXX..XXXXXXX 100644
90
+++ b/hw/block/xen-block.c
44
--- a/qom/object_interfaces.c
91
@@ -XXX,XX +XXX,XX @@
45
+++ b/qom/object_interfaces.c
92
#include "qapi/visitor.h"
46
@@ -XXX,XX +XXX,XX @@
93
#include "qapi/qmp/qdict.h"
47
#include "qapi/qmp/qerror.h"
48
#include "qapi/qmp/qjson.h"
49
#include "qapi/qmp/qstring.h"
94
#include "qapi/qmp/qstring.h"
50
+#include "qapi/qobject-input-visitor.h"
95
+#include "qom/object_interfaces.h"
51
#include "qom/object_interfaces.h"
96
#include "hw/xen/xen_common.h"
52
#include "qemu/help_option.h"
97
#include "hw/block/xen_blkif.h"
53
#include "qemu/module.h"
98
#include "hw/qdev-properties.h"
54
@@ -XXX,XX +XXX,XX @@ out:
99
@@ -XXX,XX +XXX,XX @@ static XenBlockIOThread *xen_block_iothread_create(const char *id,
55
return obj;
100
{
101
XenBlockIOThread *iothread = g_new(XenBlockIOThread, 1);
102
Error *local_err = NULL;
103
+ QDict *opts;
104
+ QObject *ret_data;
105
106
iothread->id = g_strdup(id);
107
108
- qmp_object_add(TYPE_IOTHREAD, id, false, NULL, &local_err);
109
+ opts = qdict_new();
110
+ qdict_put_str(opts, "qom-type", TYPE_IOTHREAD);
111
+ qdict_put_str(opts, "id", id);
112
+ qmp_object_add(opts, &ret_data, &local_err);
113
+ qobject_unref(opts);
114
+ qobject_unref(ret_data);
115
+
116
if (local_err) {
117
error_propagate(errp, local_err);
118
119
diff --git a/monitor/misc.c b/monitor/misc.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/monitor/misc.c
122
+++ b/monitor/misc.c
123
@@ -XXX,XX +XXX,XX @@ static void monitor_init_qmp_commands(void)
124
QCO_NO_OPTIONS);
125
qmp_register_command(&qmp_commands, "netdev_add", qmp_netdev_add,
126
QCO_NO_OPTIONS);
127
+ qmp_register_command(&qmp_commands, "object-add", qmp_object_add,
128
+ QCO_NO_OPTIONS);
129
130
QTAILQ_INIT(&qmp_cap_negotiation_commands);
131
qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
132
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/qom/qom-qmp-cmds.c
135
+++ b/qom/qom-qmp-cmds.c
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;
56
}
146
}
57
147
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
148
-void qmp_object_add(const char *type, const char *id,
59
+{
149
- bool has_props, QObject *props, Error **errp)
60
+ Visitor *v;
150
+void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
61
+ Object *obj;
151
{
62
+ g_autofree char *type = NULL;
152
+ QObject *props;
63
+ g_autofree char *id = NULL;
153
QDict *pdict;
64
+
154
Visitor *v;
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
155
Object *obj;
156
+ const char *type;
157
+ const char *id;
158
159
+ type = qdict_get_try_str(qdict, "qom-type");
66
+ if (!type) {
160
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
161
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
162
+ return;
163
+ } else {
164
+ type = g_strdup(type);
165
+ qdict_del(qdict, "qom-type");
69
+ }
166
+ }
70
+ qdict_del(qdict, "qom-type");
167
+
71
+
168
+ id = qdict_get_try_str(qdict, "id");
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
169
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
170
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
171
+ return;
172
+ } else {
173
+ id = g_strdup(id);
174
+ qdict_del(qdict, "id");
76
+ }
175
+ }
77
+ qdict_del(qdict, "id");
176
+
78
+
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);
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
199
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
200
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
201
visit_free(v);
82
+ object_unref(obj);
202
if (obj) {
83
+}
203
object_unref(obj);
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
86
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
90
+++ b/qom/qom-qmp-cmds.c
91
@@ -XXX,XX +XXX,XX @@
92
#include "qapi/qapi-commands-qom.h"
93
#include "qapi/qmp/qdict.h"
94
#include "qapi/qmp/qerror.h"
95
-#include "qapi/qobject-input-visitor.h"
96
#include "qemu/cutils.h"
97
#include "qom/object_interfaces.h"
98
#include "qom/qom-qobject.h"
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
100
{
101
QObject *props;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
126
}
204
}
127
205
- qobject_unref(pdict);
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
206
+ *ret_data = QOBJECT(qdict_new());
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
133
}
207
}
134
208
135
void qmp_object_del(const char *id, Error **errp)
209
void qmp_object_del(const char *id, Error **errp)
136
--
210
--
137
2.25.3
211
2.20.1
138
212
139
213
diff view generated by jsdifflib
New patch
1
Add a command line option to create user-creatable QOM objects.
1
2
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
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(-)
12
13
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/qemu-storage-daemon.c
16
+++ b/qemu-storage-daemon.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "qapi/error.h"
19
#include "qapi/qapi-visit-block-core.h"
20
#include "qapi/qapi-commands-block-core.h"
21
+#include "qapi/qmp/qdict.h"
22
#include "qapi/qobject-input-visitor.h"
23
24
#include "qemu-common.h"
25
#include "qemu-version.h"
26
#include "qemu/config-file.h"
27
#include "qemu/error-report.h"
28
+#include "qemu/help_option.h"
29
#include "qemu/log.h"
30
#include "qemu/main-loop.h"
31
#include "qemu/module.h"
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());
52
}
53
54
enum {
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
108
index XXXXXXX..XXXXXXX 100644
109
--- a/Makefile.objs
110
+++ b/Makefile.objs
111
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
112
# storage-daemon-obj-y is code used by qemu-storage-daemon (these objects are
113
# used for system emulation, too, but specified separately there)
114
115
-storage-daemon-obj-y = block/
116
+storage-daemon-obj-y = block/ qom/
117
storage-daemon-obj-y += blockdev.o iothread.o
118
119
######################################################################
120
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
121
index XXXXXXX..XXXXXXX 100644
122
--- a/qom/Makefile.objs
123
+++ b/qom/Makefile.objs
124
@@ -XXX,XX +XXX,XX @@ qom-obj-y = object.o container.o qom-qobject.o
125
qom-obj-y += object_interfaces.o
126
127
common-obj-$(CONFIG_SOFTMMU) += qom-hmp-cmds.o qom-qmp-cmds.o
128
+storage-daemon-obj-y += qom-qmp-cmds.o
129
--
130
2.20.1
131
132
diff view generated by jsdifflib
New patch
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.
1
6
7
Example (only with required options):
8
9
--nbd-server addr.type=inet,addr.host=localhost,addr.port=10809
10
11
Signed-off-by: Kevin Wolf <kwolf@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>
15
---
16
qapi/block-core.json | 24 ++++++++++++++++++++++++
17
include/block/nbd.h | 1 +
18
blockdev-nbd.c | 5 +++++
19
qemu-storage-daemon.c | 26 +++++++++++++++++++++++++-
20
Makefile.objs | 2 +-
21
5 files changed, 56 insertions(+), 2 deletions(-)
22
23
diff --git a/qapi/block-core.json b/qapi/block-core.json
24
index XXXXXXX..XXXXXXX 100644
25
--- a/qapi/block-core.json
26
+++ b/qapi/block-core.json
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:
54
#
55
@@ -XXX,XX +XXX,XX @@
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
63
##
64
{ 'command': 'nbd-server-start',
65
diff --git a/include/block/nbd.h b/include/block/nbd.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/block/nbd.h
68
+++ b/include/block/nbd.h
69
@@ -XXX,XX +XXX,XX @@ void nbd_client_put(NBDClient *client);
70
71
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
72
const char *tls_authz, Error **errp);
73
+void nbd_server_start_options(NbdServerOptions *arg, Error **errp);
74
75
/* nbd_read
76
* Reads @size bytes from @ioc. Returns 0 on success.
77
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/blockdev-nbd.c
80
+++ b/blockdev-nbd.c
81
@@ -XXX,XX +XXX,XX @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
82
nbd_server = NULL;
83
}
84
85
+void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
86
+{
87
+ nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, errp);
88
+}
89
+
90
void qmp_nbd_server_start(SocketAddressLegacy *addr,
91
bool has_tls_creds, const char *tls_creds,
92
bool has_tls_authz, const char *tls_authz,
93
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/qemu-storage-daemon.c
96
+++ b/qemu-storage-daemon.c
97
@@ -XXX,XX +XXX,XX @@
98
#include <getopt.h>
99
100
#include "block/block.h"
101
+#include "block/nbd.h"
102
#include "crypto/init.h"
103
104
#include "qapi/error.h"
105
-#include "qapi/qapi-visit-block-core.h"
106
+#include "qapi/qapi-commands-block.h"
107
#include "qapi/qapi-commands-block-core.h"
108
+#include "qapi/qapi-visit-block.h"
109
+#include "qapi/qapi-visit-block-core.h"
110
#include "qapi/qmp/qdict.h"
111
#include "qapi/qobject-input-visitor.h"
112
113
@@ -XXX,XX +XXX,XX @@ static void help(void)
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;
150
+
151
+ v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
152
+ visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
153
+ visit_free(v);
154
+
155
+ nbd_server_start_options(options, &error_fatal);
156
+ qapi_free_NbdServerOptions(options);
157
+ break;
158
+ }
159
case OPTION_OBJECT:
160
{
161
QemuOpts *opts;
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
175
--
176
2.20.1
177
178
diff view generated by jsdifflib
New patch
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.
1
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Message-Id: <20200224143008.13362-11-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 | 18 ++++++++++++++----
11
blockdev-nbd.c | 35 ++++++++++++++++-------------------
12
monitor/hmp-cmds.c | 21 +++++++++++++++++----
13
3 files changed, 47 insertions(+), 27 deletions(-)
14
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
16
index XXXXXXX..XXXXXXX 100644
17
--- a/qapi/block-core.json
18
+++ b/qapi/block-core.json
19
@@ -XXX,XX +XXX,XX @@
20
'*tls-authz': 'str'} }
21
22
##
23
-# @nbd-server-add:
24
+# @BlockExportNbd:
25
#
26
-# Export a block node to QEMU's embedded NBD server.
27
+# An NBD block export.
28
#
29
# @device: The device name or node name of the node to be exported
30
#
31
@@ -XXX,XX +XXX,XX @@
32
# NBD client can use NBD_OPT_SET_META_CONTEXT with
33
# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
34
#
35
+# Since: 5.0
36
+##
37
+{ 'struct': 'BlockExportNbd',
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.
48
#
49
# Since: 1.3.0
50
##
51
{ 'command': 'nbd-server-add',
52
- 'data': {'device': 'str', '*name': 'str', '*description': 'str',
53
- '*writable': 'bool', '*bitmap': 'str' } }
54
+ 'data': 'BlockExportNbd', 'boxed': true }
55
56
##
57
# @NbdServerRemoveMode:
58
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/blockdev-nbd.c
61
+++ b/blockdev-nbd.c
62
@@ -XXX,XX +XXX,XX @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
63
qapi_free_SocketAddress(addr_flat);
64
}
65
66
-void qmp_nbd_server_add(const char *device, bool has_name, const char *name,
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)
71
{
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);
178
}
179
180
--
181
2.20.1
182
183
diff view generated by jsdifflib
New patch
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:
1
5
6
--export nbd,device=disk,name=test-export,writable=on
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Message-Id: <20200224143008.13362-12-kwolf@redhat.com>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
qapi/block-core.json | 27 +++++++++++++++++++++++++++
14
qemu-storage-daemon.c | 31 +++++++++++++++++++++++++++++++
15
2 files changed, 58 insertions(+)
16
17
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
19
--- a/qapi/block-core.json
20
+++ b/qapi/block-core.json
21
@@ -XXX,XX +XXX,XX @@
22
##
23
{ 'command': 'nbd-server-stop' }
24
25
+##
26
+# @BlockExportType:
27
+#
28
+# An enumeration of block export types
29
+#
30
+# @nbd: NBD export
31
+#
32
+# Since: 4.2
33
+##
34
+{ 'enum': 'BlockExportType',
35
+ 'data': [ 'nbd' ] }
36
+
37
+##
38
+# @BlockExport:
39
+#
40
+# Describes a block export, i.e. how single node should be exported on an
41
+# external interface.
42
+#
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
56
index XXXXXXX..XXXXXXX 100644
57
--- a/qemu-storage-daemon.c
58
+++ b/qemu-storage-daemon.c
59
@@ -XXX,XX +XXX,XX @@ static void help(void)
60
" [,driver specific parameters...]\n"
61
" configure a block backend\n"
62
"\n"
63
+" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
64
+" [,writable=on|off][,bitmap=<name>]\n"
65
+" export the specified block node over NBD\n"
66
+" (requires --nbd-server)\n"
67
+"\n"
68
" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
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;
124
--
125
2.20.1
126
127
diff view generated by jsdifflib
1
We want to keep TEST_IMG for the full path of the main test image, but
1
Instead of exiting after processing all command line options, start a
2
filter_testfiles() must be called for other test images before replacing
2
main loop and keep processing events until exit is requested with a
3
other things like the image format because the test directory path could
3
signal (e.g. SIGINT).
4
contain the format as a substring.
5
4
6
Insert a filter_testfiles() call between both.
5
Now qemu-storage-daemon can be used as an alternative for qemu-nbd that
6
provides a few features that were previously only available from QMP,
7
such as access to options only available with -blockdev and the socket
8
types 'vsock' and 'fd'.
7
9
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20200224143008.13362-13-kwolf@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
---
14
tests/qemu-iotests/iotests.py | 5 +++--
15
qemu-storage-daemon.c | 13 +++++++++++++
15
1 file changed, 3 insertions(+), 2 deletions(-)
16
Makefile.objs | 2 ++
17
2 files changed, 15 insertions(+)
16
18
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
19
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
21
--- a/qemu-storage-daemon.c
20
+++ b/tests/qemu-iotests/iotests.py
22
+++ b/qemu-storage-daemon.c
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
23
@@ -XXX,XX +XXX,XX @@
22
for line in output.split('\n'):
24
#include "qemu/option.h"
23
if 'disk size' in line or 'actual-size' in line:
25
#include "qom/object_interfaces.h"
24
continue
26
25
- line = line.replace(filename, 'TEST_IMG') \
27
+#include "sysemu/runstate.h"
26
- .replace(imgfmt, 'IMGFMT')
28
#include "trace/control.h"
27
+ line = line.replace(filename, 'TEST_IMG')
29
28
+ line = filter_testfiles(line)
30
+static volatile bool exit_requested = false;
29
+ line = line.replace(imgfmt, 'IMGFMT')
31
+
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
32
+void qemu_system_killed(int signal, pid_t pid)
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
33
+{
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
34
+ exit_requested = true;
35
+}
36
+
37
static void help(void)
38
{
39
printf(
40
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
41
42
error_init(argv[0]);
43
qemu_init_exec_dir(argv[0]);
44
+ os_setup_signal_handling();
45
46
module_call_init(MODULE_INIT_QOM);
47
module_call_init(MODULE_INIT_TRACE);
48
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
49
qemu_init_main_loop(&error_fatal);
50
process_options(argc, argv);
51
52
+ while (!exit_requested) {
53
+ main_loop_wait(false);
54
+ }
55
+
56
return EXIT_SUCCESS;
57
}
58
diff --git a/Makefile.objs b/Makefile.objs
59
index XXXXXXX..XXXXXXX 100644
60
--- a/Makefile.objs
61
+++ b/Makefile.objs
62
@@ -XXX,XX +XXX,XX @@ endif # CONFIG_SOFTMMU or CONFIG_TOOLS
63
64
storage-daemon-obj-y = block/ qom/
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
33
--
71
--
34
2.25.3
72
2.20.1
35
73
36
74
diff view generated by jsdifflib
1
After processing the option string with the keyval parser, we get a
1
This adds a --chardev option to the storage daemon that works the same
2
QDict that contains only strings. This QDict must be fed to a keyval
2
as the -chardev option of the system emulator.
3
visitor which converts the strings into the right data types.
4
3
5
qmp_object_add(), however, uses the normal QObject input visitor, which
4
The syntax of the --chardev option is still considered unstable. We want
6
expects a QDict where all properties already have the QType that matches
5
to QAPIfy it and will potentially make changes to its syntax while
7
the data type required by the QOM object type.
6
converting it. However, we haven't decided yet on a design for the
7
QAPIfication, so QemuOpts will have to do for now.
8
8
9
Change the --object implementation in qemu-storage-daemon so that it
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
10
Message-Id: <20200224143008.13362-14-kwolf@redhat.com>
11
directly instead and pass it a new keyval boolean that decides which
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
12
visitor must be used.
13
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
13
---
17
include/qom/object_interfaces.h | 6 +++++-
14
qemu-storage-daemon.c | 24 ++++++++++++++++++++++++
18
qemu-storage-daemon.c | 4 +---
15
Makefile | 2 +-
19
qom/object_interfaces.c | 8 ++++++--
16
2 files changed, 25 insertions(+), 1 deletion(-)
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
22
17
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/qom/object_interfaces.h
26
+++ b/include/qom/object_interfaces.h
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
28
/**
29
* user_creatable_add_dict:
30
* @qdict: the object definition
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
32
+ * assume that all @qdict values are strings); otherwise, use
33
+ * the normal QObject visitor (i.e. assume all @qdict values
34
+ * have the QType expected by the QOM object type)
35
* @errp: if an error occurs, a pointer to an area to store the error
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
18
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
20
--- a/qemu-storage-daemon.c
50
+++ b/qemu-storage-daemon.c
21
+++ b/qemu-storage-daemon.c
22
@@ -XXX,XX +XXX,XX @@
23
24
#include "block/block.h"
25
#include "block/nbd.h"
26
+#include "chardev/char.h"
27
#include "crypto/init.h"
28
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",
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
55
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
52
QemuOpts *opts;
56
53
const char *type;
57
static const struct option long_options[] = {
54
QDict *args;
58
{"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
55
- QObject *ret_data = NULL;
59
+ {"chardev", required_argument, NULL, OPTION_CHARDEV},
56
60
{"export", required_argument, NULL, OPTION_EXPORT},
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
61
{"help", no_argument, NULL, 'h'},
58
* unconditionall try QemuOpts first. */
62
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
63
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
64
qapi_free_BlockdevOptions(options);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
65
break;
68
}
66
}
69
default:
67
+ case OPTION_CHARDEV:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
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
71
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
88
--- a/Makefile
73
+++ b/qom/object_interfaces.c
89
+++ b/Makefile
74
@@ -XXX,XX +XXX,XX @@ out:
90
@@ -XXX,XX +XXX,XX @@ qemu-img.o: qemu-img-cmds.h
75
return obj;
91
qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
76
}
92
qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
77
93
qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS)
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
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)
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
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)
80
{
96
81
Visitor *v;
97
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS)
82
Object *obj;
98
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
84
}
85
qdict_del(qdict, "id");
86
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
88
+ if (keyval) {
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
90
+ } else {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
106
}
107
108
void qmp_object_del(const char *id, Error **errp)
109
--
99
--
110
2.25.3
100
2.20.1
111
101
112
102
diff view generated by jsdifflib
1
The raw format driver can simply forward the flag and let its bs->file
1
Before we can add the monitor to qemu-storage-daemon, we need to add a
2
child take care of actually providing the zeros.
2
stubs for monitor_fdsets_cleanup().
3
4
We also need to make sure that stubs that are actually implemented in
5
the monitor core aren't linked to qemu-storage-daemon so that we don't
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.
3
8
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20200224143008.13362-15-kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
13
---
11
block/raw-format.c | 4 +++-
14
stubs/monitor-core.c | 21 +++++++++++++++++++++
12
1 file changed, 3 insertions(+), 1 deletion(-)
15
stubs/monitor.c | 15 ++-------------
16
stubs/Makefile.objs | 1 +
17
3 files changed, 24 insertions(+), 13 deletions(-)
18
create mode 100644 stubs/monitor-core.c
13
19
14
diff --git a/block/raw-format.c b/block/raw-format.c
20
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
21
new file mode 100644
22
index XXXXXXX..XXXXXXX
23
--- /dev/null
24
+++ b/stubs/monitor-core.c
25
@@ -XXX,XX +XXX,XX @@
26
+#include "qemu/osdep.h"
27
+#include "monitor/monitor.h"
28
+#include "qemu-common.h"
29
+#include "qapi/qapi-emit-events.h"
30
+
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
+}
45
+
46
+
47
diff --git a/stubs/monitor.c b/stubs/monitor.c
15
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
16
--- a/block/raw-format.c
49
--- a/stubs/monitor.c
17
+++ b/block/raw-format.c
50
+++ b/stubs/monitor.c
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
51
@@ -XXX,XX +XXX,XX @@
19
52
#include "qemu/osdep.h"
20
s->size = offset;
53
#include "qapi/error.h"
21
offset += s->offset;
54
-#include "qapi/qapi-emit-events.h"
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
55
#include "monitor/monitor.h"
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
56
-
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;
24
}
69
}
25
70
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
71
-void monitor_init_qmp(Chardev *chr, bool pretty)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
72
-{
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
73
-}
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
74
-
30
bs->file->bs->supported_zero_flags);
75
void monitor_init_hmp(Chardev *chr, bool use_readline)
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
76
{
32
+ BDRV_REQ_ZERO_WRITE;
77
}
33
78
34
if (bs->probed && !bdrv_is_read_only(bs)) {
79
-void qapi_event_emit(QAPIEvent event, QDict *qdict)
35
bdrv_refresh_filename(bs->file->bs);
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
36
--
95
--
37
2.25.3
96
2.20.1
38
97
39
98
diff view generated by jsdifflib
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.
4
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
6
Message-Id: <20200224143008.13362-16-kwolf@redhat.com>
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
9
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
10
qapi/pragma.json | 24 ++++++++++++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
11
qapi/qapi-schema.json | 25 +------------------------
9
tests/qemu-iotests/group | 1 +
12
qapi/Makefile.objs | 2 +-
10
3 files changed, 424 insertions(+)
13
3 files changed, 26 insertions(+), 25 deletions(-)
11
create mode 100755 tests/qemu-iotests/274
14
create mode 100644 qapi/pragma.json
12
create mode 100644 tests/qemu-iotests/274.out
13
15
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
16
diff --git a/qapi/pragma.json b/qapi/pragma.json
15
new file mode 100755
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/tests/qemu-iotests/274
19
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
21
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
23
+#
24
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
28
+#
29
+# This program is distributed in the hope that it will be useful,
30
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
+# GNU General Public License for more details.
33
+#
34
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
41
+import iotests
42
+
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
137
+
138
+ iotests.log('== Resize tests ==')
139
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
162
+ top_size_old)
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
164
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
166
+ #
167
+ # In theory, leaving base_size to top_size_new unallocated would be
168
+ # correct, but in practice, if we zero out anything, we zero out
169
+ # everything up to top_size_new.
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
171
+ '--preallocation', prealloc, top, top_size_new)
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
173
+ iotests.qemu_io_log('-c', 'map', top)
174
+ iotests.qemu_img_log('map', '--output=json', top)
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
176
new file mode 100644
17
new file mode 100644
177
index XXXXXXX..XXXXXXX
18
index XXXXXXX..XXXXXXX
178
--- /dev/null
19
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
20
+++ b/qapi/pragma.json
180
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
22
+{ 'pragma': { 'doc-required': true } }
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
183
+
23
+
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
24
+# Whitelists to permit QAPI rule violations; think twice before you
185
+
25
+# add to them!
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
26
+{ 'pragma': {
187
+
27
+ # Commands allowed to return a non-dictionary:
188
+wrote 2097152/2097152 bytes at offset 0
28
+ 'returns-whitelist': [
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
29
+ 'human-monitor-command',
190
+
30
+ 'qom-get',
191
+=== Check visible data ===
31
+ 'query-migrate-cache-size',
192
+read 1048576/1048576 bytes at offset 0
32
+ 'query-tpm-models',
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
33
+ 'query-tpm-types',
194
+
34
+ 'ringbuf-read' ],
195
+read 1048576/1048576 bytes at offset 1048576
35
+ 'name-case-whitelist': [
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
36
+ 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
197
+
37
+ 'CpuInfoMIPS', # PC, visible through query-cpu
198
+=== Checking allocation status ===
38
+ 'CpuInfoTricore', # PC, visible through query-cpu
199
+1048576/1048576 bytes allocated at offset 0 bytes
39
+ 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings
200
+1048576/1048576 bytes allocated at offset 1 MiB
40
+ 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings
201
+
41
+ 'QapiErrorClass', # all members, visible through errors
202
+0/1048576 bytes allocated at offset 0 bytes
42
+ 'UuidInfo', # UUID, visible through query-uuid
203
+0/0 bytes allocated at offset 1 MiB
43
+ 'X86CPURegister32', # all members, visible indirectly through qom-get
204
+
44
+ 'CpuInfo' # CPU, visible through query-cpu
205
+0/1048576 bytes allocated at offset 0 bytes
45
+ ] } }
206
+0/1048576 bytes allocated at offset 1 MiB
46
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
450
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
451
--- a/tests/qemu-iotests/group
48
--- a/qapi/qapi-schema.json
452
+++ b/tests/qemu-iotests/group
49
+++ b/qapi/qapi-schema.json
453
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@
454
270 rw backing quick
51
#
455
272 rw
52
##
456
273 backing quick
53
457
+274 rw backing
54
-{ 'pragma': { 'doc-required': true } }
458
277 rw quick
55
-
459
279 rw backing quick
56
-# Whitelists to permit QAPI rule violations; think twice before you
460
280 rw migration quick
57
-# add to them!
58
-{ 'pragma': {
59
- # Commands allowed to return a non-dictionary:
60
- 'returns-whitelist': [
61
- 'human-monitor-command',
62
- 'qom-get',
63
- 'query-migrate-cache-size',
64
- 'query-tpm-models',
65
- 'query-tpm-types',
66
- 'ringbuf-read' ],
67
- 'name-case-whitelist': [
68
- 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
69
- 'CpuInfoMIPS', # PC, visible through query-cpu
70
- 'CpuInfoTricore', # PC, visible through query-cpu
71
- 'BlockdevVmdkSubformat', # all members, to match VMDK spec spellings
72
- 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spellings
73
- 'QapiErrorClass', # all members, visible through errors
74
- 'UuidInfo', # UUID, visible through query-uuid
75
- 'X86CPURegister32', # all members, visible indirectly through qom-get
76
- 'CpuInfo' # CPU, visible through query-cpu
77
- ] } }
78
+{ 'include': 'pragma.json' }
79
80
# Documentation generated with qapi-gen.py is in source order, with
81
# included sub-schemas inserted at the first include directive
82
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
83
index XXXXXXX..XXXXXXX 100644
84
--- a/qapi/Makefile.objs
85
+++ b/qapi/Makefile.objs
86
@@ -XXX,XX +XXX,XX @@ util-obj-y += qapi-util.o
87
88
QAPI_COMMON_MODULES = audio authz block-core block char common control crypto
89
QAPI_COMMON_MODULES += dump error introspect job machine migration misc
90
-QAPI_COMMON_MODULES += net qdev qom rdma rocker run-state sockets tpm
91
+QAPI_COMMON_MODULES += net pragma qdev qom rdma rocker run-state sockets tpm
92
QAPI_COMMON_MODULES += trace transaction ui
93
QAPI_TARGET_MODULES = machine-target misc-target
94
QAPI_MODULES = $(QAPI_COMMON_MODULES) $(QAPI_TARGET_MODULES)
461
--
95
--
462
2.25.3
96
2.20.1
463
97
464
98
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@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
Test 244 checks the expected behavior of qcow2 external data files
5
This will cause some change in those error messages for the monitor
4
with respect to zero and discarded clusters. Filesystems however
6
options in the system emulator that are now generated by the visitor
5
are free to ignore discard requests, and this seems to be the
7
rather than explicitly checked in monitor_init_opts().
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
9
8
10
This fixes docker tests on RHEL8.
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
10
Message-Id: <20200224143008.13362-17-kwolf@redhat.com>
12
Cc: Kevin Wolf <kwolf@redhat.com>
11
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Cc: qemu-block@nongnu.org
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
13
---
18
tests/qemu-iotests/244 | 10 ++++++++--
14
qapi/control.json | 36 ++++++++++++++++++
19
tests/qemu-iotests/244.out | 9 ++++++---
15
include/monitor/monitor.h | 2 +
20
2 files changed, 14 insertions(+), 5 deletions(-)
16
monitor/monitor.c | 77 +++++++++++++++++++++------------------
17
3 files changed, 80 insertions(+), 35 deletions(-)
21
18
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
19
diff --git a/qapi/control.json b/qapi/control.json
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
25
+++ b/tests/qemu-iotests/244
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
27
echo
28
$QEMU_IO -c 'read -P 0 0 1M' \
29
-c 'read -P 0x11 1M 1M' \
30
- -c 'read -P 0 2M 2M' \
31
-c 'read -P 0x11 4M 1M' \
32
-c 'read -P 0 5M 1M' \
33
-f raw "$TEST_IMG.data" |
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
35
-f $IMGFMT "$TEST_IMG" |
36
_filter_qemu_io
37
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
39
+# they can contain stale data in the external data file. Instead, zero
40
+# clusters must be zeroed in the external data file too.
41
echo
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
43
+$QEMU_IO -c 'read -P 0 0 1M' \
44
+ -c 'read -P 0x11 1M 1M' \
45
+ -c 'read -P 0 3M 3M' \
46
+ -f raw "$TEST_IMG".data |
47
+ _filter_qemu_io
48
49
echo -n "qcow2 file size after I/O: "
50
du -b $TEST_IMG | cut -f1
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
52
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/244.out
21
--- a/qapi/control.json
54
+++ b/tests/qemu-iotests/244.out
22
+++ b/qapi/control.json
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
23
@@ -XXX,XX +XXX,XX @@
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
24
# <- { "return": {} }
57
read 1048576/1048576 bytes at offset 1048576
25
##
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
26
{ 'command': 'quit' }
59
-read 2097152/2097152 bytes at offset 2097152
27
+
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
28
+##
61
read 1048576/1048576 bytes at offset 4194304
29
+# @MonitorMode:
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
30
+#
63
read 1048576/1048576 bytes at offset 5242880
31
+# An enumeration of monitor modes.
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
32
+#
65
read 4194304/4194304 bytes at offset 2097152
33
+# @readline: HMP monitor (human-oriented command line interface)
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
34
+#
67
35
+# @control: QMP monitor (JSON-based machine interface)
68
-Images are identical.
36
+#
69
+read 1048576/1048576 bytes at offset 0
37
+# Since: 5.0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
38
+##
71
+read 1048576/1048576 bytes at offset 1048576
39
+{ 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] }
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
40
+
73
+read 3145728/3145728 bytes at offset 3145728
41
+##
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
42
+# @MonitorOptions:
75
qcow2 file size after I/O: 327680
43
+#
76
44
+# Options to be used for adding a new monitor.
77
=== bdrv_co_block_status test for file and offset=0 ===
45
+#
46
+# @id: Name of the monitor
47
+#
48
+# @mode: Selects the monitor mode (default: readline)
49
+#
50
+# @pretty: Enables pretty printing (QMP only)
51
+#
52
+# @chardev: Name of a character device to expose the monitor on
53
+#
54
+# Since: 5.0
55
+##
56
+{ 'struct': 'MonitorOptions',
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)
103
{
104
Chardev *chr;
105
- bool qmp;
106
- bool pretty = false;
107
- const char *chardev;
108
- const char *mode;
109
-
110
- mode = qemu_opt_get(opts, "mode");
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;
125
}
126
127
- if (!qmp && qemu_opt_get(opts, "pretty")) {
128
- warn_report("'pretty' is deprecated for HMP monitors, it has no effect "
129
- "and will be removed in future versions");
130
- }
131
- if (qemu_opt_get_bool(opts, "pretty", 0)) {
132
- pretty = true;
133
+ switch (opts->mode) {
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
+}
159
+
160
+int monitor_init_opts(QemuOpts *opts, Error **errp)
161
+{
162
+ Visitor *v;
163
+ MonitorOptions *options;
164
+ Error *local_err = NULL;
165
+
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;
172
}
173
174
- if (qmp) {
175
- monitor_init_qmp(chr, pretty);
176
- } else {
177
- monitor_init_hmp(chr, true);
178
+ monitor_init(options, &local_err);
179
+ qapi_free_MonitorOptions(options);
180
+
181
+out:
182
+ if (local_err) {
183
+ error_propagate(errp, local_err);
184
+ return -1;
185
}
186
return 0;
187
}
78
--
188
--
79
2.25.3
189
2.20.1
80
190
81
191
diff view generated by jsdifflib
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
1
Trying to attach a QMP monitor to a chardev that is already in use
2
the parameter in the node level interfaces bdrv_co_truncate() and
2
results in a crash because monitor_init_qmp() passes &error_abort to
3
bdrv_truncate().
3
qemu_chr_fe_init():
4
5
$ ./x86_64-softmmu/qemu-system-x86_64 --chardev stdio,id=foo --mon foo,mode=control --mon foo,mode=control
6
Unexpected error in qemu_chr_fe_init() at chardev/char-fe.c:220:
7
qemu-system-x86_64: --mon foo,mode=control: Device 'foo' is in use
8
Abgebrochen (Speicherabzug geschrieben)
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.
4
12
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Message-Id: <20200224143008.13362-18-kwolf@redhat.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
15
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
17
---
12
include/block/block.h | 5 +++--
18
include/monitor/monitor.h | 2 +-
13
block/block-backend.c | 2 +-
19
monitor/monitor.c | 7 ++++++-
14
block/crypto.c | 2 +-
20
monitor/qmp.c | 11 +++++++----
15
block/io.c | 12 +++++++-----
21
stubs/monitor-core.c | 2 +-
16
block/parallels.c | 6 +++---
22
tests/test-util-sockets.c | 2 +-
17
block/qcow.c | 4 ++--
23
5 files changed, 16 insertions(+), 8 deletions(-)
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
26
24
27
diff --git a/include/block/block.h b/include/block/block.h
25
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
28
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block.h
27
--- a/include/monitor/monitor.h
30
+++ b/include/block/block.h
28
+++ b/include/monitor/monitor.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
29
@@ -XXX,XX +XXX,XX @@ bool monitor_cur_is_qmp(void);
32
void bdrv_refresh_filename(BlockDriverState *bs);
30
33
31
void monitor_init_globals(void);
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
32
void monitor_init_globals_core(void);
35
- PreallocMode prealloc, Error **errp);
33
-void monitor_init_qmp(Chardev *chr, bool pretty);
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
34
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
37
+ Error **errp);
35
void monitor_init_hmp(Chardev *chr, bool use_readline);
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
36
int monitor_init(MonitorOptions *opts, Error **errp);
39
- PreallocMode prealloc, Error **errp);
37
int monitor_init_opts(QemuOpts *opts, Error **errp);
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
diff --git a/monitor/monitor.c b/monitor/monitor.c
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
44
diff --git a/block/block-backend.c b/block/block-backend.c
45
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
40
--- a/monitor/monitor.c
47
+++ b/block/block-backend.c
41
+++ b/monitor/monitor.c
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
42
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals_core(void)
49
return -ENOMEDIUM;
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();
50
}
61
}
51
62
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
63
+ if (local_err) {
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
64
+ error_propagate(errp, local_err);
65
+ return -1;
66
+ }
67
return 0;
54
}
68
}
55
69
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
70
diff --git a/monitor/qmp.c b/monitor/qmp.c
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
72
--- a/monitor/qmp.c
60
+++ b/block/crypto.c
73
+++ b/monitor/qmp.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
74
@@ -XXX,XX +XXX,XX @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
62
75
monitor_list_append(&mon->common);
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
76
}
68
77
69
static void block_crypto_close(BlockDriverState *bs)
78
-void monitor_init_qmp(Chardev *chr, bool pretty)
70
diff --git a/block/io.c b/block/io.c
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
71
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
104
--- a/stubs/monitor-core.c
73
+++ b/block/io.c
105
+++ b/stubs/monitor-core.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
106
@@ -XXX,XX +XXX,XX @@
75
* 'offset' bytes in length.
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)
76
*/
120
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
121
__thread Monitor *cur_mon;
78
- PreallocMode prealloc, Error **errp)
122
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
123
-void monitor_init_qmp(Chardev *chr, bool pretty) {}
80
+ Error **errp)
124
+void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {}
81
{
125
void monitor_init_hmp(Chardev *chr, bool use_readline) {}
82
BlockDriverState *bs = child->bs;
126
83
BlockDriver *drv = bs->drv;
127
84
BdrvTrackedRequest req;
85
- BdrvRequestFlags flags = 0;
86
int64_t old_size, new_bytes;
87
int ret;
88
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
90
}
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
92
} else if (bs->file && drv->is_filter) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
149
error_report_err(local_err);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
307
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
309
index XXXXXXX..XXXXXXX 100644
310
--- a/tests/test-block-iothread.c
311
+++ b/tests/test-block-iothread.c
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
313
int ret;
314
315
/* Normal success path */
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
318
g_assert_cmpint(ret, ==, 0);
319
320
/* Early error: Negative offset */
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
323
g_assert_cmpint(ret, ==, -EINVAL);
324
325
/* Error: Read-only image */
326
c->bs->read_only = true;
327
c->bs->open_flags &= ~BDRV_O_RDWR;
328
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
331
g_assert_cmpint(ret, ==, -EACCES);
332
333
c->bs->read_only = false;
334
--
128
--
335
2.25.3
129
2.20.1
336
130
337
131
diff view generated by jsdifflib
1
When extending the size of an image that has a backing file larger than
1
Trying to attach a HMP monitor to a chardev that is already in use
2
its old size, make sure that the backing file data doesn't become
2
results in a crash because monitor_init_hmp() passes &error_abort to
3
visible in the guest, but the added area is properly zeroed out.
3
qemu_chr_fe_init():
4
4
5
Consider the following scenario where the overlay is shorter than its
5
$ ./x86_64-softmmu/qemu-system-x86_64 --chardev stdio,id=foo --mon foo --mon foo
6
backing file:
6
QEMU 4.2.50 monitor - type 'help' for more information
7
(qemu) Unexpected error in qemu_chr_fe_init() at chardev/char-fe.c:220:
8
qemu-system-x86_64: --mon foo: Device 'foo' is in use
9
Abgebrochen (Speicherabzug geschrieben)
7
10
8
base.qcow2: AAAAAAAA
11
Fix this by allowing monitor_init_hmp() to return an error and passing
9
overlay.qcow2: BBBB
12
any error in qemu_chr_fe_init() to its caller instead of aborting.
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
13
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <20200224143008.13362-19-kwolf@redhat.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
16
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
18
---
36
block/io.c | 25 +++++++++++++++++++++++++
19
include/monitor/monitor.h | 2 +-
37
1 file changed, 25 insertions(+)
20
chardev/char.c | 8 +++++++-
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(-)
38
27
39
diff --git a/block/io.c b/block/io.c
28
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
40
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
41
--- a/block/io.c
30
--- a/include/monitor/monitor.h
42
+++ b/block/io.c
31
+++ b/include/monitor/monitor.h
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
32
@@ -XXX,XX +XXX,XX @@ bool monitor_cur_is_qmp(void);
44
goto out;
33
void monitor_init_globals(void);
45
}
34
void monitor_init_globals_core(void);
46
35
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
47
+ /*
36
-void monitor_init_hmp(Chardev *chr, bool use_readline);
48
+ * If the image has a backing file that is large enough that it would
37
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
49
+ * provide data for the new area, we cannot leave it unallocated because
38
int monitor_init(MonitorOptions *opts, Error **errp);
50
+ * then the backing file content would become visible. Instead, zero-fill
39
int monitor_init_opts(QemuOpts *opts, Error **errp);
51
+ * the new area.
40
void monitor_cleanup(void);
52
+ *
41
diff --git a/chardev/char.c b/chardev/char.c
53
+ * Note that if the image has a backing file, but was opened without the
42
index XXXXXXX..XXXXXXX 100644
54
+ * backing file, taking care of keeping things consistent with that backing
43
--- a/chardev/char.c
55
+ * file is the user's responsibility.
44
+++ b/chardev/char.c
56
+ */
45
@@ -XXX,XX +XXX,XX @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename,
57
+ if (new_bytes && bs->backing) {
46
58
+ int64_t backing_len;
47
if (qemu_opt_get_bool(opts, "mux", 0)) {
59
+
48
assert(permit_mux_mon);
60
+ backing_len = bdrv_getlength(backing_bs(bs));
49
- monitor_init_hmp(chr, true);
61
+ if (backing_len < 0) {
50
+ monitor_init_hmp(chr, true, &err);
62
+ ret = backing_len;
51
+ if (err) {
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
52
+ error_report_err(err);
53
+ object_unparent(OBJECT(chr));
54
+ chr = NULL;
64
+ goto out;
55
+ goto out;
65
+ }
56
+ }
66
+
57
}
67
+ if (backing_len > old_size) {
58
68
+ flags |= BDRV_REQ_ZERO_WRITE;
59
out:
69
+ }
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);
79
}
80
81
-void monitor_init_hmp(Chardev *chr, bool use_readline)
82
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp)
83
{
84
MonitorHMP *mon = g_new0(MonitorHMP, 1);
85
86
+ if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) {
87
+ g_free(mon);
88
+ return;
70
+ }
89
+ }
71
+
90
+
72
if (drv->bdrv_co_truncate) {
91
monitor_data_init(&mon->common, false, false, false);
73
if (flags & ~bs->supported_truncate_flags) {
92
- qemu_chr_fe_init(&mon->common.chr, chr, &error_abort);
74
error_setg(errp, "Block driver does not support requested flags");
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)
119
{
120
}
121
122
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/tests/test-util-sockets.c
125
+++ b/tests/test-util-sockets.c
126
@@ -XXX,XX +XXX,XX @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
127
__thread Monitor *cur_mon;
128
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
129
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) {}
130
-void monitor_init_hmp(Chardev *chr, bool use_readline) {}
131
+void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) {}
132
133
134
static void test_socket_fd_pass_name_good(void)
75
--
135
--
76
2.25.3
136
2.20.1
77
137
78
138
diff view generated by jsdifflib
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
1
Add a new parameter allow_hmp to monitor_init() so that the storage
2
daemon can disable HMP.
2
3
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
Message-Id: <20200224143008.13362-20-kwolf@redhat.com>
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
8
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
8
---
16
hw/block/nvme.h | 2 +
9
qapi/control.json | 3 ++-
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
10
include/monitor/monitor.h | 2 +-
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
11
monitor/monitor.c | 12 ++++++++++--
19
hw/block/Makefile.objs | 2 +-
12
3 files changed, 13 insertions(+), 4 deletions(-)
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
22
13
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
14
diff --git a/qapi/control.json b/qapi/control.json
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/block/nvme.h
16
--- a/qapi/control.json
26
+++ b/hw/block/nvme.h
17
+++ b/qapi/control.json
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
18
@@ -XXX,XX +XXX,XX @@
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
19
#
29
20
# @id: Name of the monitor
30
char *serial;
21
#
31
+ HostMemoryBackend *pmrdev;
22
-# @mode: Selects the monitor mode (default: readline)
32
+
23
+# @mode: Selects the monitor mode (default: readline in the system
33
NvmeNamespace *namespaces;
24
+# emulator, control in qemu-storage-daemon)
34
NvmeSQueue **sq;
25
#
35
NvmeCQueue **cq;
26
# @pretty: Enables pretty printing (QMP only)
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
27
#
28
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
37
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
30
--- a/include/monitor/monitor.h
39
+++ b/include/block/nvme.h
31
+++ b/include/monitor/monitor.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
32
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals(void);
41
uint64_t acq;
33
void monitor_init_globals_core(void);
42
uint32_t cmbloc;
34
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
43
uint32_t cmbsz;
35
void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
44
+ uint8_t padding[3520]; /* not used by QEMU */
36
-int monitor_init(MonitorOptions *opts, Error **errp);
45
+ uint32_t pmrcap;
37
+int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp);
46
+ uint32_t pmrctl;
38
int monitor_init_opts(QemuOpts *opts, Error **errp);
47
+ uint32_t pmrsts;
39
void monitor_cleanup(void);
48
+ uint32_t pmrebs;
40
49
+ uint32_t pmrswtp;
41
diff --git a/monitor/monitor.c b/monitor/monitor.c
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
43
--- a/monitor/monitor.c
250
+++ b/hw/block/nvme.c
44
+++ b/monitor/monitor.c
251
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@ void monitor_init_globals_core(void)
252
* -drive file=<file>,if=none,id=<drive_id>
46
NULL);
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
47
}
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
48
255
+ * [pmrdev=<mem_backend_file_id>,] \
49
-int monitor_init(MonitorOptions *opts, Error **errp)
256
* num_queues=<N[optional]>
50
+int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp)
257
*
51
{
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
52
Chardev *chr;
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
53
Error *local_err = NULL;
260
+ *
54
@@ -XXX,XX +XXX,XX @@ int monitor_init(MonitorOptions *opts, Error **errp)
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
55
return -1;
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
309
}
56
}
310
57
311
if (addr < sizeof(n->bar)) {
58
+ if (!opts->has_mode) {
312
+ /*
59
+ opts->mode = allow_hmp ? MONITOR_MODE_READLINE : MONITOR_MODE_CONTROL;
313
+ * When PMRWBM bit 1 is set then read from
314
+ * from PMRSTS should ensure prior writes
315
+ * made it to persistent media
316
+ */
317
+ if (addr == 0xE08 &&
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
320
+ 0, n->pmrdev->size);
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
328
}
329
+
330
+ if (!n->cmb_size_mb && n->pmrdev) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
334
+ g_free(path);
335
+ return;
336
+ }
337
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
340
+ return;
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
344
+ }
60
+ }
345
+
61
+
346
blkconf_blocksizes(&n->conf);
62
switch (opts->mode) {
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
63
case MONITOR_MODE_CONTROL:
348
false, errp)) {
64
monitor_init_qmp(chr, opts->pretty, &local_err);
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
65
break;
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
66
case MONITOR_MODE_READLINE:
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
67
+ if (!allow_hmp) {
352
68
+ error_setg(errp, "Only QMP is supported");
353
+ } else if (n->pmrdev) {
69
+ return -1;
354
+ /* Controller Capabilities register */
70
+ }
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
71
if (opts->pretty) {
356
+
72
warn_report("'pretty' is deprecated for HMP monitors, it has no "
357
+ /* PMR Capabities register */
73
"effect and will be removed in future versions");
358
+ n->bar.pmrcap = 0;
74
@@ -XXX,XX +XXX,XX @@ int monitor_init_opts(QemuOpts *opts, Error **errp)
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
75
goto out;
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
363
+ /* Turn on bit 1 support */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
367
+
368
+ /* PMR Control register */
369
+ n->bar.pmrctl = 0;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
398
}
76
}
399
77
400
for (i = 0; i < n->num_namespaces; i++) {
78
- monitor_init(options, &local_err);
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
79
+ monitor_init(options, true, &local_err);
402
if (n->cmb_size_mb) {
80
qapi_free_MonitorOptions(options);
403
g_free(n->cmbuf);
81
404
}
82
out:
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
410
}
411
412
static Property nvme_props[] = {
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
420
index XXXXXXX..XXXXXXX 100644
421
--- a/hw/block/Makefile.objs
422
+++ b/hw/block/Makefile.objs
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
424
common-obj-$(CONFIG_XEN) += xen-block.o
425
common-obj-$(CONFIG_ECC) += ecc.o
426
common-obj-$(CONFIG_ONENAND) += onenand.o
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
428
common-obj-$(CONFIG_SWIM) += swim.o
429
430
common-obj-$(CONFIG_SH4) += tc58128.o
431
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
435
436
obj-y += dataplane/
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/block/trace-events
440
+++ b/hw/block/trace-events
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
452
--
83
--
453
2.25.3
84
2.20.1
454
85
455
86
diff view generated by jsdifflib
New patch
1
1
This adds and parses the --monitor option, so that a QMP monitor can be
2
used in the storage daemon. The monitor offers commands defined in the
3
QAPI schema at storage-daemon/qapi/qapi-schema.json.
4
5
The --monitor options currently allows to create multiple monitors with
6
the same ID. This part of the interface is considered unstable. We will
7
reject such configurations as soon as we have a design for the monitor
8
subsystem to perform these checks. (In the system emulator, we depend on
9
QemuOpts rejecting duplicate IDs.)
10
11
Signed-off-by: Kevin Wolf <kwolf@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>
15
---
16
qapi/transaction.json | 2 +-
17
qemu-storage-daemon.c | 47 ++++++++++++++++++++++++++--
18
scripts/qapi/gen.py | 5 +++
19
Makefile | 33 +++++++++++++++++++
20
Makefile.objs | 4 +--
21
monitor/Makefile.objs | 2 ++
22
qapi/Makefile.objs | 5 +++
23
storage-daemon/Makefile.objs | 1 +
24
storage-daemon/qapi/Makefile.objs | 1 +
25
storage-daemon/qapi/qapi-schema.json | 26 +++++++++++++++
26
10 files changed, 121 insertions(+), 5 deletions(-)
27
create mode 100644 storage-daemon/Makefile.objs
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
35
@@ -XXX,XX +XXX,XX @@
36
# = Transactions
37
##
38
39
-{ 'include': 'block.json' }
40
+{ 'include': 'block-core.json' }
41
42
##
43
# @Abort:
44
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/qemu-storage-daemon.c
47
+++ b/qemu-storage-daemon.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "block/nbd.h"
50
#include "chardev/char.h"
51
#include "crypto/init.h"
52
+#include "monitor/monitor.h"
53
+#include "monitor/monitor-internal.h"
54
55
#include "qapi/error.h"
56
-#include "qapi/qapi-commands-block.h"
57
-#include "qapi/qapi-commands-block-core.h"
58
#include "qapi/qapi-visit-block.h"
59
#include "qapi/qapi-visit-block-core.h"
60
+#include "qapi/qapi-visit-control.h"
61
#include "qapi/qmp/qdict.h"
62
+#include "qapi/qmp/qstring.h"
63
#include "qapi/qobject-input-visitor.h"
64
65
#include "qemu-common.h"
66
@@ -XXX,XX +XXX,XX @@
67
#include "qemu/option.h"
68
#include "qom/object_interfaces.h"
69
70
+#include "storage-daemon/qapi/qapi-commands.h"
71
+#include "storage-daemon/qapi/qapi-init-commands.h"
72
+
73
#include "sysemu/runstate.h"
74
#include "trace/control.h"
75
76
@@ -XXX,XX +XXX,XX @@ void qemu_system_killed(int signal, pid_t pid)
77
exit_requested = true;
78
}
79
80
+void qmp_quit(Error **errp)
81
+{
82
+ exit_requested = true;
83
+}
84
+
85
static void help(void)
86
{
87
printf(
88
@@ -XXX,XX +XXX,XX @@ static void help(void)
89
" export the specified block node over NBD\n"
90
" (requires --nbd-server)\n"
91
"\n"
92
+" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
93
+" configure a QMP monitor\n"
94
+"\n"
95
" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
96
" [,tls-creds=<id>][,tls-authz=<id>]\n"
97
" --nbd-server addr.type=unix,addr.path=<path>\n"
98
@@ -XXX,XX +XXX,XX @@ enum {
99
OPTION_BLOCKDEV = 256,
100
OPTION_CHARDEV,
101
OPTION_EXPORT,
102
+ OPTION_MONITOR,
103
OPTION_NBD_SERVER,
104
OPTION_OBJECT,
105
};
106
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_object_opts = {
107
},
108
};
109
110
+static void init_qmp_commands(void)
111
+{
112
+ qmp_init_marshal(&qmp_commands);
113
+ qmp_register_command(&qmp_commands, "query-qmp-schema",
114
+ qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
115
+
116
+ QTAILQ_INIT(&qmp_cap_negotiation_commands);
117
+ qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
118
+ qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
119
+}
120
+
121
static void init_export(BlockExport *export, Error **errp)
122
{
123
switch (export->type) {
124
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
125
{"chardev", required_argument, NULL, OPTION_CHARDEV},
126
{"export", required_argument, NULL, OPTION_EXPORT},
127
{"help", no_argument, NULL, 'h'},
128
+ {"monitor", required_argument, NULL, OPTION_MONITOR},
129
{"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
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
277
new file mode 100644
278
index XXXXXXX..XXXXXXX
279
--- /dev/null
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
295
@@ -XXX,XX +XXX,XX @@
296
+# -*- Mode: Python -*-
297
+
298
+# Note that modules are shared with the QEMU main schema under the assumption
299
+# that the storage daemon schema is a subset of the main schema. For the shared
300
+# modules, no code is generated here, but we reuse the code files generated
301
+# from the main schema.
302
+#
303
+# If you wish to extend the storage daemon schema to contain things that are
304
+# not in the main schema, be aware that array types of types defined in shared
305
+# modules are only generated if an array of the respective type is already used
306
+# in the main schema. Therefore, if you use such arrays, you may need to define
307
+# the array type in the main schema, even if it is unused outside of the
308
+# storage daemon.
309
+
310
+{ 'include': '../../qapi/pragma.json' }
311
+
312
+{ 'include': '../../qapi/block-core.json' }
313
+{ 'include': '../../qapi/char.json' }
314
+{ 'include': '../../qapi/common.json' }
315
+{ 'include': '../../qapi/control.json' }
316
+{ 'include': '../../qapi/crypto.json' }
317
+{ 'include': '../../qapi/introspect.json' }
318
+{ 'include': '../../qapi/job.json' }
319
+{ 'include': '../../qapi/qom.json' }
320
+{ 'include': '../../qapi/sockets.json' }
321
+{ 'include': '../../qapi/transaction.json' }
322
--
323
2.20.1
324
325
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Florian Florensa <fflorensa@online.net>
2
2
3
Backing files and raw external data files are mutually exclusive.
3
Starting from ceph Nautilus, RBD has support for namespaces, allowing
4
The documentation of the raw external data bit (in autoclear_features)
4
for finer grain ACLs on images inside a pool, and tenant isolation.
5
already indicates that, but we should also mention it on the other
6
side.
7
5
8
Suggested-by: Eric Blake <eblake@redhat.com>
6
In the rbd cli tool documentation, the new image-spec and snap-spec are :
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
- [pool-name/[namespace-name/]]image-name
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
8
- [pool-name/[namespace-name/]]image-name@snap-name
11
Reviewed-by: Eric Blake <eblake@redhat.com>
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>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
28
---
14
docs/interop/qcow2.txt | 3 +++
29
qapi/block-core.json | 3 +++
15
1 file changed, 3 insertions(+)
30
block/rbd.c | 44 +++++++++++++++++++++++++++++++-------------
31
2 files changed, 34 insertions(+), 13 deletions(-)
16
32
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
33
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
35
--- a/qapi/block-core.json
20
+++ b/docs/interop/qcow2.txt
36
+++ b/qapi/block-core.json
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
37
@@ -XXX,XX +XXX,XX @@
22
is stored (NB: The string is not null terminated). 0 if the
38
#
23
image doesn't have a backing file.
39
# @pool: Ceph pool name.
24
40
#
25
+ Note: backing files are incompatible with raw external data
41
+# @namespace: Rados namespace name in the Ceph pool. (Since 5.0)
26
+ files (auto-clear feature bit 1).
42
+#
27
+
43
# @image: Image name in the Ceph pool.
28
16 - 19: backing_file_size
44
#
29
Length of the backing file name in bytes. Must not be
45
# @conf: path to Ceph configuration file. Values
30
longer than 1023 bytes. Undefined if the image doesn't have
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;
150
31
--
151
--
32
2.25.3
152
2.20.1
33
153
34
154
diff view generated by jsdifflib
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
1
We'll want to test more than one successful case in the future, so
2
OS, so we can advertise the flag and just ignore it.
2
prepare the test for that by a refactoring that runs each scenario in a
3
separate VM.
4
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.
3
9
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Tested-by: Peter Krempa <pkrempa@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-Id: <20200306141413.30705-2-kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
14
---
11
block/file-posix.c | 4 ++++
15
tests/qemu-iotests/245 | 47 ++++++++++++++++++++++++++++++--------
12
1 file changed, 4 insertions(+)
16
tests/qemu-iotests/245.out | 4 ++--
17
2 files changed, 39 insertions(+), 12 deletions(-)
13
18
14
diff --git a/block/file-posix.c b/block/file-posix.c
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
15
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
16
--- a/block/file-posix.c
92
--- a/tests/qemu-iotests/245.out
17
+++ b/block/file-posix.c
93
+++ b/tests/qemu-iotests/245.out
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
94
@@ -XXX,XX +XXX,XX @@
19
#endif
95
-..................
20
96
+.....................
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
97
----------------------------------------------------------------------
22
+ if (S_ISREG(st.st_mode)) {
98
-Ran 18 tests
23
+ /* When extending regular files, we get zeros from the OS */
99
+Ran 21 tests
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
100
25
+ }
101
OK
26
ret = 0;
102
{"execute": "job-finalize", "arguments": {"id": "commit0"}}
27
fail:
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
29
--
103
--
30
2.25.3
104
2.20.1
31
105
32
106
diff view generated by jsdifflib
1
Now that node level interface bdrv_truncate() supports passing request
1
This patch allows bdrv_reopen() (and therefore the x-blockdev-reopen QMP
2
flags to the block driver, expose this on the BlockBackend level, too.
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.
3
5
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Tested-by: Peter Krempa <pkrempa@redhat.com>
8
Message-Id: <20200306141413.30705-3-kwolf@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
---
11
include/sysemu/block-backend.h | 2 +-
12
block.c | 32 ++++++++++++++++++++++++++------
12
block.c | 3 ++-
13
tests/qemu-iotests/245 | 8 +++-----
13
block/block-backend.c | 4 ++--
14
2 files changed, 29 insertions(+), 11 deletions(-)
14
block/commit.c | 4 ++--
15
block/crypto.c | 2 +-
16
block/mirror.c | 2 +-
17
block/qcow2.c | 4 ++--
18
block/qed.c | 2 +-
19
block/vdi.c | 2 +-
20
block/vhdx.c | 4 ++--
21
block/vmdk.c | 6 +++---
22
block/vpc.c | 2 +-
23
blockdev.c | 2 +-
24
qemu-img.c | 2 +-
25
qemu-io-cmds.c | 2 +-
26
15 files changed, 22 insertions(+), 21 deletions(-)
27
15
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend.h
31
+++ b/include/sysemu/block-backend.h
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
34
int bytes);
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
- PreallocMode prealloc, Error **errp);
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
40
int64_t pos, int size);
41
diff --git a/block.c b/block.c
16
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
18
--- a/block.c
44
+++ b/block.c
19
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
20
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_perm(BlockReopenQueue *q, BlockDriverState *bs,
46
int64_t size;
21
*shared = cumulative_shared_perms;
47
int ret;
48
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
51
+ &local_err);
52
if (ret < 0 && ret != -ENOTSUP) {
53
error_propagate(errp, local_err);
54
return ret;
55
diff --git a/block/block-backend.c b/block/block-backend.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/block-backend.c
58
+++ b/block/block-backend.c
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
60
}
22
}
61
23
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
24
+static bool bdrv_reopen_can_attach(BlockDriverState *parent,
63
- PreallocMode prealloc, Error **errp)
25
+ BdrvChild *child,
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
26
+ BlockDriverState *new_child,
65
{
27
+ Error **errp)
66
if (!blk_is_available(blk)) {
28
+{
67
error_setg(errp, "No medium inserted");
29
+ AioContext *parent_ctx = bdrv_get_aio_context(parent);
68
return -ENOMEDIUM;
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,
69
}
51
}
70
52
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
53
/*
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
54
- * TODO: before removing the x- prefix from x-blockdev-reopen we
73
}
55
- * should move the new backing file into the right AioContext
74
56
- * instead of returning an error.
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
+ * Check AioContext compatibility so that the bdrv_set_backing_hd() call in
76
diff --git a/block/commit.c b/block/commit.c
58
+ * bdrv_reopen_commit() won't fail.
77
index XXXXXXX..XXXXXXX 100644
59
*/
78
--- a/block/commit.c
60
if (new_backing_bs) {
79
+++ b/block/commit.c
61
- if (bdrv_get_aio_context(new_backing_bs) != bdrv_get_aio_context(bs)) {
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
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;
66
}
81
}
67
}
82
68
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
83
if (base_len < len) {
69
index XXXXXXX..XXXXXXX 100755
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
70
--- a/tests/qemu-iotests/245
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
71
+++ b/tests/qemu-iotests/245
86
if (ret) {
72
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
87
goto out;
73
# neither of them can switch to the other AioContext
88
}
74
def test_iothreads_error(self):
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
75
self.run_test_iothreads('iothread0', 'iothread1',
90
* grow the backing file image if possible. If not possible,
76
- "Cannot use a new backing file with a different AioContext")
91
* we must return an error */
77
+ "Cannot change iothread of active block backend")
92
if (length > backing_length) {
78
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
79
def test_iothreads_compatible_users(self):
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
80
self.run_test_iothreads('iothread0', 'iothread0')
95
&local_err);
81
96
if (ret < 0) {
82
def test_iothreads_switch_backing(self):
97
error_report_err(local_err);
83
- self.run_test_iothreads('iothread0', None,
98
diff --git a/block/crypto.c b/block/crypto.c
84
- "Cannot use a new backing file with a different AioContext")
99
index XXXXXXX..XXXXXXX 100644
85
+ self.run_test_iothreads('iothread0', None)
100
--- a/block/crypto.c
86
101
+++ b/block/crypto.c
87
def test_iothreads_switch_overlay(self):
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
88
- self.run_test_iothreads(None, 'iothread0',
103
* which will be used by the crypto header
89
- "Cannot use a new backing file with a different AioContext")
104
*/
90
+ self.run_test_iothreads(None, 'iothread0')
105
return blk_truncate(data->blk, data->size + headerlen, false,
91
106
- data->prealloc, errp);
92
if __name__ == '__main__':
107
+ data->prealloc, 0, errp);
93
iotests.main(supported_fmts=["qcow2"],
108
}
109
110
111
diff --git a/block/mirror.c b/block/mirror.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/block/mirror.c
114
+++ b/block/mirror.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
116
117
if (s->bdev_length > base_length) {
118
ret = blk_truncate(s->target, s->bdev_length, false,
119
- PREALLOC_MODE_OFF, NULL);
120
+ PREALLOC_MODE_OFF, 0, NULL);
121
if (ret < 0) {
122
goto immediate_exit;
123
}
124
diff --git a/block/qcow2.c b/block/qcow2.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/block/qcow2.c
127
+++ b/block/qcow2.c
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
129
130
/* Okay, now that we have a valid image, let's give it the right size */
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
132
- errp);
133
+ 0, errp);
134
if (ret < 0) {
135
error_prepend(errp, "Could not resize image: ");
136
goto out;
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
185
} else if (type == VHDX_TYPE_FIXED) {
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
187
- PREALLOC_MODE_OFF, errp);
188
+ PREALLOC_MODE_OFF, 0, errp);
189
if (ret < 0) {
190
goto exit;
191
}
192
diff --git a/block/vmdk.c b/block/vmdk.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/block/vmdk.c
195
+++ b/block/vmdk.c
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
197
int gd_buf_size;
198
199
if (flat) {
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
202
goto exit;
203
}
204
magic = cpu_to_be32(VMDK4_MAGIC);
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
206
}
207
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
209
- PREALLOC_MODE_OFF, errp);
210
+ PREALLOC_MODE_OFF, 0, errp);
211
if (ret < 0) {
212
goto exit;
213
}
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
216
* for description file */
217
if (desc_offset == 0) {
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
220
if (ret < 0) {
221
goto exit;
222
}
223
diff --git a/block/vpc.c b/block/vpc.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/block/vpc.c
226
+++ b/block/vpc.c
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
228
/* Add footer to total size */
229
total_size += HEADER_SIZE;
230
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
233
if (ret < 0) {
234
return ret;
235
}
236
diff --git a/blockdev.c b/blockdev.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/blockdev.c
239
+++ b/blockdev.c
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
241
}
242
243
bdrv_drained_begin(bs);
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
246
bdrv_drained_end(bs);
247
248
out:
249
diff --git a/qemu-img.c b/qemu-img.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/qemu-img.c
252
+++ b/qemu-img.c
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
254
* resizing, so pass @exact=true. It is of no use to report
255
* success when the image has not actually been resized.
256
*/
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
259
if (!ret) {
260
qprintf(quiet, "Image resized.\n");
261
} else {
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
263
index XXXXXXX..XXXXXXX 100644
264
--- a/qemu-io-cmds.c
265
+++ b/qemu-io-cmds.c
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
267
* exact=true. It is better to err on the "emit more errors" side
268
* than to be overly permissive.
269
*/
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
272
if (ret < 0) {
273
error_report_err(local_err);
274
return ret;
275
--
94
--
276
2.25.3
95
2.20.1
277
96
278
97
diff view generated by jsdifflib