summaryrefslogtreecommitdiff
path: root/qapi
diff options
context:
space:
mode:
authorSeokYeon Hwang <syeon.hwang@samsung.com>2017-06-28 16:20:50 +0900
committerSeokYeon Hwang <syeon.hwang@samsung.com>2017-06-28 16:21:16 +0900
commite6230f92c2a7c924f4092b877ee70a74f76e6841 (patch)
tree3f6f4a364da163b80c9669f903eda6f8aeb4d19b /qapi
parente9775ba331166fc2de29a387b1070281c8ec0985 (diff)
parent6ca9395b240883513b16a1875a7080b081612c57 (diff)
downloadqemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.tar.gz
qemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.tar.bz2
qemu-e6230f92c2a7c924f4092b877ee70a74f76e6841.zip
Merge spin into tizen
Change-Id: I00f8d0dbf2d26f3c9c6754b9f1d986355037f5bb
Diffstat (limited to 'qapi')
-rw-r--r--qapi/Makefile.objs4
-rw-r--r--qapi/block-core.json551
-rw-r--r--qapi/block.json47
-rw-r--r--qapi/common.json14
-rw-r--r--qapi/crypto.json45
-rw-r--r--qapi/event.json58
-rw-r--r--qapi/introspect.json28
-rw-r--r--qapi/qapi-clone-visitor.c2
-rw-r--r--qapi/qapi-visit-core.c51
-rw-r--r--qapi/qmp-event.c17
-rw-r--r--qapi/qmp-output-visitor.c256
-rw-r--r--qapi/qmp-registry.c8
-rw-r--r--qapi/qobject-input-visitor.c (renamed from qapi/qmp-input-visitor.c)221
-rw-r--r--qapi/qobject-output-visitor.c254
-rw-r--r--qapi/rocker.json2
-rw-r--r--qapi/trace-events33
-rw-r--r--qapi/trace.json8
17 files changed, 967 insertions, 632 deletions
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 7ea4aebb00..33906ff321 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -1,5 +1,5 @@
-util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
-util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
+util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qobject-input-visitor.o
+util-obj-y += qobject-output-visitor.o qmp-registry.o qmp-dispatch.o
util-obj-y += string-input-visitor.o string-output-visitor.o
util-obj-y += opts-visitor.o qapi-clone-visitor.o
util-obj-y += qmp-event.o
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5e2d7d78d2..6b42216960 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -6,7 +6,7 @@
{ 'include': 'common.json' }
##
-# @SnapshotInfo
+# @SnapshotInfo:
#
# @id: unique snapshot id
#
@@ -25,7 +25,6 @@
# Since: 1.3
#
##
-
{ 'struct': 'SnapshotInfo',
'data': { 'id': 'str', 'name': 'str', 'vm-state-size': 'int',
'date-sec': 'int', 'date-nsec': 'int',
@@ -81,7 +80,6 @@
#
# Since: 1.7
##
-
{ 'union': 'ImageInfoSpecific',
'data': {
'qcow2': 'ImageInfoSpecificQCow2',
@@ -129,7 +127,6 @@
# Since: 1.3
#
##
-
{ 'struct': 'ImageInfo',
'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool',
'*actual-size': 'int', 'virtual-size': 'int',
@@ -181,7 +178,6 @@
# Since: 1.4
#
##
-
{ 'struct': 'ImageCheck',
'data': {'filename': 'str', 'format': 'str', 'check-errors': 'int',
'*image-end-offset': 'int', '*corruptions': 'int', '*leaks': 'int',
@@ -217,7 +213,7 @@
'*filename': 'str' } }
##
-# @BlockdevCacheInfo
+# @BlockdevCacheInfo:
#
# Cache mode information for a block device
#
@@ -247,11 +243,12 @@
# 0.14.0 this can be: 'blkdebug', 'bochs', 'cloop', 'cow', 'dmg',
# 'file', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
# 'http', 'https', 'luks', 'nbd', 'parallels', 'qcow',
-# 'qcow2', 'raw', 'tftp', 'vdi', 'vmdk', 'vpc', 'vvfat'
+# 'qcow2', 'raw', 'vdi', 'vmdk', 'vpc', 'vvfat'
# 2.2: 'archipelago' added, 'cow' dropped
# 2.3: 'host_floppy' deprecated
# 2.5: 'host_floppy' dropped
# 2.6: 'luks' added
+# 2.8: 'replication' added, 'tftp' dropped
#
# @backing_file: #optional the name of the backing file (for copy-on-write)
#
@@ -381,7 +378,7 @@
# @offset: if present, the image file stores the data for this range in
# raw format at the given offset.
#
-# Since 1.7
+# Since: 1.7
##
{ 'struct': 'BlockDeviceMapEntry',
'data': { 'start': 'int', 'length': 'int', 'depth': 'int', 'zero': 'bool',
@@ -517,7 +514,6 @@
#
# Since: 2.5
##
-
{ 'struct': 'BlockDeviceTimedStats',
'data': { 'interval_length': 'int', 'min_rd_latency_ns': 'int',
'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int',
@@ -794,7 +790,7 @@
'*node-name': 'str', 'password': 'str'} }
##
-# @block_resize
+# @block_resize:
#
# Resize a block image while a guest is running.
#
@@ -816,7 +812,7 @@
'size': 'int' }}
##
-# @NewImageMode
+# @NewImageMode:
#
# An enumeration that tells QEMU how to set the backing file path in
# a new image file.
@@ -833,7 +829,7 @@
'data': [ 'existing', 'absolute-paths' ] }
##
-# @BlockdevSnapshotSync
+# @BlockdevSnapshotSync:
#
# Either @device or @node-name must be set but not both.
#
@@ -856,7 +852,7 @@
'*format': 'str', '*mode': 'NewImageMode' } }
##
-# @BlockdevSnapshot
+# @BlockdevSnapshot:
#
# @node: device or node name that will have a snapshot created.
#
@@ -865,18 +861,18 @@
# It must not have a current backing file (this can be
# achieved by passing "backing": "" to blockdev-add).
#
-# Since 2.5
+# Since: 2.5
##
{ 'struct': 'BlockdevSnapshot',
'data': { 'node': 'str', 'overlay': 'str' } }
##
-# @DriveBackup
+# @DriveBackup:
#
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the name of the device which should be copied.
+# @device: the device name or node-name of a root node which should be copied.
#
# @target: the target of the new image. If the file exists, or if it
# is a device, the existing file/device will be used as the new
@@ -898,6 +894,9 @@
# Must be present if sync is "incremental", must NOT be present
# otherwise. (Since 2.4)
#
+# @compress: #optional true to compress data, if the target format supports it.
+# (default: false) (since 2.8)
+#
# @on-source-error: #optional the action to take on an error on the source,
# default 'report'. 'stop' and 'enospc' can only be used
# if the block device supports io-status (see BlockInfo).
@@ -906,26 +905,26 @@
# default 'report' (no limitations, since this applies to
# a different block device than @device).
#
-# Note that @on-source-error and @on-target-error only affect background I/O.
-# If an error occurs during a guest write request, the device's rerror/werror
-# actions will be used.
+# Note: @on-source-error and @on-target-error only affect background
+# I/O. If an error occurs during a guest write request, the device's
+# rerror/werror actions will be used.
#
# Since: 1.6
##
{ 'struct': 'DriveBackup',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*format': 'str', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode',
- '*speed': 'int', '*bitmap': 'str',
+ '*speed': 'int', '*bitmap': 'str', '*compress': 'bool',
'*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
##
-# @BlockdevBackup
+# @BlockdevBackup:
#
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the name of the device which should be copied.
+# @device: the device name or node-name of a root node which should be copied.
#
# @target: the device name or node-name of the backup target node.
#
@@ -936,6 +935,9 @@
# @speed: #optional the maximum speed, in bytes per second. The default is 0,
# for unlimited.
#
+# @compress: #optional true to compress data, if the target format supports it.
+# (default: false) (since 2.8)
+#
# @on-source-error: #optional the action to take on an error on the source,
# default 'report'. 'stop' and 'enospc' can only be used
# if the block device supports io-status (see BlockInfo).
@@ -944,9 +946,9 @@
# default 'report' (no limitations, since this applies to
# a different block device than @device).
#
-# Note that @on-source-error and @on-target-error only affect background I/O.
-# If an error occurs during a guest write request, the device's rerror/werror
-# actions will be used.
+# Note: @on-source-error and @on-target-error only affect background
+# I/O. If an error occurs during a guest write request, the device's
+# rerror/werror actions will be used.
#
# Since: 2.3
##
@@ -954,11 +956,12 @@
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'sync': 'MirrorSyncMode',
'*speed': 'int',
+ '*compress': 'bool',
'*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError' } }
##
-# @blockdev-snapshot-sync
+# @blockdev-snapshot-sync:
#
# Generates a synchronous snapshot of a block device.
#
@@ -967,26 +970,26 @@
# Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound
#
-# Since 0.14.0
+# Since: 0.14.0
##
{ 'command': 'blockdev-snapshot-sync',
'data': 'BlockdevSnapshotSync' }
##
-# @blockdev-snapshot
+# @blockdev-snapshot:
#
# Generates a snapshot of a block device.
#
# For the arguments, see the documentation of BlockdevSnapshot.
#
-# Since 2.5
+# Since: 2.5
##
{ 'command': 'blockdev-snapshot',
'data': 'BlockdevSnapshot' }
##
-# @change-backing-file
+# @change-backing-file:
#
# Change the backing file in the image file metadata. This does not
# cause QEMU to reopen the image file to reparse the backing filename
@@ -998,7 +1001,8 @@
# @image-node-name: The name of the block driver state node of the
# image to modify.
#
-# @device: The name of the device that owns image-node-name.
+# @device: The device name or node-name of the root node that owns
+# image-node-name.
#
# @backing-file: The string to write as the backing file. This
# string is not validated, so care should be taken
@@ -1012,7 +1016,7 @@
'backing-file': 'str' } }
##
-# @block-commit
+# @block-commit:
#
# Live commit of data from overlay image nodes into backing nodes - i.e.,
# writes data between 'top' and 'base' into 'base'.
@@ -1020,7 +1024,7 @@
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the name of the device
+# @device: the device name or node-name of a root node
#
# @base: #optional The file name of the backing image to write data into.
# If not specified, this is the deepest backing image
@@ -1075,7 +1079,7 @@
'*backing-file': 'str', '*speed': 'int' } }
##
-# @drive-backup
+# @drive-backup:
#
# Start a point-in-time copy of a block device to a new destination. The
# status of ongoing drive-backup operations can be checked with
@@ -1086,14 +1090,15 @@
# For the arguments, see the documentation of DriveBackup.
#
# Returns: nothing on success
-# If @device is not a valid block device, DeviceNotFound
+# If @device is not a valid block device, GenericError
#
-# Since 1.6
+# Since: 1.6
##
-{ 'command': 'drive-backup', 'data': 'DriveBackup' }
+{ 'command': 'drive-backup', 'boxed': true,
+ 'data': 'DriveBackup' }
##
-# @blockdev-backup
+# @blockdev-backup:
#
# Start a point-in-time copy of a block device to a new destination. The
# status of ongoing blockdev-backup operations can be checked with
@@ -1103,46 +1108,51 @@
#
# For the arguments, see the documentation of BlockdevBackup.
#
-# Since 2.3
+# Returns: nothing on success
+# If @device is not a valid block device, DeviceNotFound
+#
+# Since: 2.3
##
-{ 'command': 'blockdev-backup', 'data': 'BlockdevBackup' }
+{ 'command': 'blockdev-backup', 'boxed': true,
+ 'data': 'BlockdevBackup' }
##
-# @query-named-block-nodes
+# @query-named-block-nodes:
#
# Get the named block driver list
#
# Returns: the list of BlockDeviceInfo
#
-# Since 2.0
+# Since: 2.0
##
{ 'command': 'query-named-block-nodes', 'returns': [ 'BlockDeviceInfo' ] }
##
-# @drive-mirror
+# @drive-mirror:
#
# Start mirroring a block device's writes to a new destination.
#
# See DriveMirror for parameter descriptions
#
# Returns: nothing on success
-# If @device is not a valid block device, DeviceNotFound
+# If @device is not a valid block device, GenericError
#
-# Since 1.3
+# Since: 1.3
##
{ 'command': 'drive-mirror', 'boxed': true,
'data': 'DriveMirror' }
##
-# DriveMirror
+# @DriveMirror:
#
# A set of parameters describing drive mirror setup.
#
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the name of the device whose writes should be mirrored.
+# @device: the device name or node-name of a root node whose writes should be
+# mirrored.
#
# @target: the target of the new image. If the file exists, or if it
# is a device, the existing file/device will be used as the new
@@ -1188,7 +1198,7 @@
# written. Both will result in identical contents.
# Default is true. (Since 2.4)
#
-# Since 1.3
+# Since: 1.3
##
{ 'struct': 'DriveMirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
@@ -1200,19 +1210,19 @@
'*unmap': 'bool' } }
##
-# @BlockDirtyBitmap
+# @BlockDirtyBitmap:
#
# @node: name of device/node which the bitmap is tracking
#
# @name: name of the dirty bitmap
#
-# Since 2.4
+# Since: 2.4
##
{ 'struct': 'BlockDirtyBitmap',
'data': { 'node': 'str', 'name': 'str' } }
##
-# @BlockDirtyBitmapAdd
+# @BlockDirtyBitmapAdd:
#
# @node: name of device/node which the bitmap is tracking
#
@@ -1221,13 +1231,13 @@
# @granularity: #optional the bitmap granularity, default is 64k for
# block-dirty-bitmap-add
#
-# Since 2.4
+# Since: 2.4
##
{ 'struct': 'BlockDirtyBitmapAdd',
'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32' } }
##
-# @block-dirty-bitmap-add
+# @block-dirty-bitmap-add:
#
# Create a dirty bitmap with a name on the node
#
@@ -1235,13 +1245,13 @@
# If @node is not a valid block device or node, DeviceNotFound
# If @name is already taken, GenericError with an explanation
#
-# Since 2.4
+# Since: 2.4
##
{ 'command': 'block-dirty-bitmap-add',
'data': 'BlockDirtyBitmapAdd' }
##
-# @block-dirty-bitmap-remove
+# @block-dirty-bitmap-remove:
#
# Remove a dirty bitmap on the node
#
@@ -1250,13 +1260,13 @@
# If @name is not found, GenericError with an explanation
# if @name is frozen by an operation, GenericError
#
-# Since 2.4
+# Since: 2.4
##
{ 'command': 'block-dirty-bitmap-remove',
'data': 'BlockDirtyBitmap' }
##
-# @block-dirty-bitmap-clear
+# @block-dirty-bitmap-clear:
#
# Clear (reset) a dirty bitmap on the device
#
@@ -1264,20 +1274,21 @@
# If @node is not a valid block device, DeviceNotFound
# If @name is not found, GenericError with an explanation
#
-# Since 2.4
+# Since: 2.4
##
{ 'command': 'block-dirty-bitmap-clear',
'data': 'BlockDirtyBitmap' }
##
-# @blockdev-mirror
+# @blockdev-mirror:
#
# Start mirroring a block device's writes to a new destination.
#
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the name of the device whose writes should be mirrored.
+# @device: The device name or node-name of a root node whose writes should be
+# mirrored.
#
# @target: the id or node-name of the block device to mirror to. This mustn't be
# attached to guest.
@@ -1310,7 +1321,7 @@
#
# Returns: nothing on success.
#
-# Since 2.6
+# Since: 2.6
##
{ 'command': 'blockdev-mirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
@@ -1357,11 +1368,13 @@
'data': 'BlockIOThrottle' }
##
-# BlockIOThrottle
+# @BlockIOThrottle:
#
# A set of parameters describing block throttling.
#
-# @device: The name of the device
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @bps: total throughput limit in bytes per second
#
@@ -1430,8 +1443,8 @@
# Since: 1.1
##
{ 'struct': 'BlockIOThrottle',
- 'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
- 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
+ 'data': { '*device': 'str', '*id': 'str', 'bps': 'int', 'bps_rd': 'int',
+ 'bps_wr': 'int', 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int',
'*bps_max': 'int', '*bps_rd_max': 'int',
'*bps_wr_max': 'int', '*iops_max': 'int',
'*iops_rd_max': 'int', '*iops_wr_max': 'int',
@@ -1451,6 +1464,13 @@
# with query-block-jobs. The operation can be stopped before it has completed
# using the block-job-cancel command.
#
+# The node that receives the data is called the top image, can be located in
+# any part of the chain (but always above the base image; see below) and can be
+# specified using its device or node name. Earlier qemu versions only allowed
+# 'device' to name the top level node; presence of the 'base-node' parameter
+# during introspection can be used as a witness of the enhanced semantics
+# of 'device'.
+#
# If a base file is specified then sectors are not copied from that base file and
# its backing chain. When streaming completes the image file will have the base
# file as its backing file. This can be used to stream a subset of the backing
@@ -1462,12 +1482,16 @@
# @job-id: #optional identifier for the newly-created block job. If
# omitted, the device name will be used. (Since 2.7)
#
-# @device: the device name
+# @device: the device or node name of the top image
+#
+# @base: #optional the common backing file name.
+# It cannot be set if @base-node is also set.
#
-# @base: #optional the common backing file name
+# @base-node: #optional the node name of the backing file.
+# It cannot be set if @base is also set. (Since 2.8)
#
-# @backing-file: #optional The backing file string to write into the active
-# layer. This filename is not validated.
+# @backing-file: #optional The backing file string to write into the top
+# image. This filename is not validated.
#
# If a pathname string is such that it cannot be
# resolved by QEMU, that means that subsequent QMP or
@@ -1487,14 +1511,11 @@
# 'stop' and 'enospc' can only be used if the block device
# supports io-status (see BlockInfo). Since 1.3.
#
-# Returns: Nothing on success
-# If @device does not exist, DeviceNotFound
-#
# Since: 1.1
##
{ 'command': 'block-stream',
'data': { '*job-id': 'str', 'device': 'str', '*base': 'str',
- '*backing-file': 'str', '*speed': 'int',
+ '*base-node': 'str', '*backing-file': 'str', '*speed': 'int',
'*on-error': 'BlockdevOnError' } }
##
@@ -1629,7 +1650,7 @@
{ 'command': 'block-job-complete', 'data': { 'device': 'str' } }
##
-# @BlockdevDiscardOptions
+# @BlockdevDiscardOptions:
#
# Determines how to handle discard requests.
#
@@ -1642,7 +1663,7 @@
'data': [ 'ignore', 'unmap' ] }
##
-# @BlockdevDetectZeroesOptions
+# @BlockdevDetectZeroesOptions:
#
# Describes the operation mode for the automatic conversion of plain
# zero writes by the OS to driver specific optimized zero write commands.
@@ -1658,7 +1679,7 @@
'data': [ 'off', 'on', 'unmap' ] }
##
-# @BlockdevAioOptions
+# @BlockdevAioOptions:
#
# Selects the AIO backend to handle I/O requests
#
@@ -1671,7 +1692,7 @@
'data': [ 'threads', 'native' ] }
##
-# @BlockdevCacheOptions
+# @BlockdevCacheOptions:
#
# Includes cache-related options for block devices
#
@@ -1687,37 +1708,44 @@
'*no-flush': 'bool' } }
##
-# @BlockdevDriver
+# @BlockdevDriver:
#
# Drivers that are supported in block device operations.
#
-# @host_device, @host_cdrom: Since 2.1
+# @host_device: Since 2.1
+# @host_cdrom: Since 2.1
# @gluster: Since 2.7
+# @nbd: Since 2.8
+# @nfs: Since 2.8
+# @replication: Since 2.8
+# @ssh: Since 2.8
#
# Since: 2.0
##
{ 'enum': 'BlockdevDriver',
'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
- 'host_device', 'http', 'https', 'luks', 'null-aio', 'null-co',
- 'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp',
- 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
+ 'host_device', 'http', 'https', 'luks', 'nbd', 'nfs', 'null-aio',
+ 'null-co', 'parallels', 'qcow', 'qcow2', 'qed', 'quorum', 'raw',
+ 'replication', 'ssh', 'vdi', 'vhdx', 'vmdk', 'vpc',
+ 'vvfat' ] }
##
-# @BlockdevOptionsFile
+# @BlockdevOptionsFile:
#
-# Driver specific block device options for the file backend and similar
-# protocols.
+# Driver specific block device options for the file backend.
#
# @filename: path to the image file
+# @aio: #optional AIO backend (default: threads) (since: 2.8)
#
# Since: 1.7
##
{ 'struct': 'BlockdevOptionsFile',
- 'data': { 'filename': 'str' } }
+ 'data': { 'filename': 'str',
+ '*aio': 'BlockdevAioOptions' } }
##
-# @BlockdevOptionsNull
+# @BlockdevOptionsNull:
#
# Driver specific block device options for the null backend.
#
@@ -1732,7 +1760,7 @@
'data': { '*size': 'int', '*latency-ns': 'uint64' } }
##
-# @BlockdevOptionsVVFAT
+# @BlockdevOptionsVVFAT:
#
# Driver specific block device options for the vvfat protocol.
#
@@ -1753,7 +1781,7 @@
'*label': 'str', '*rw': 'bool' } }
##
-# @BlockdevOptionsGenericFormat
+# @BlockdevOptionsGenericFormat:
#
# Driver specific block device options for image format that have no option
# besides their data source.
@@ -1766,7 +1794,7 @@
'data': { 'file': 'BlockdevRef' } }
##
-# @BlockdevOptionsLUKS
+# @BlockdevOptionsLUKS:
#
# Driver specific block device options for LUKS.
#
@@ -1782,7 +1810,7 @@
##
-# @BlockdevOptionsGenericCOWFormat
+# @BlockdevOptionsGenericCOWFormat:
#
# Driver specific block device options for image format that have no option
# besides their data source and an optional backing file.
@@ -1799,7 +1827,7 @@
'data': { '*backing': 'BlockdevRef' } }
##
-# @Qcow2OverlapCheckMode
+# @Qcow2OverlapCheckMode:
#
# General overlap check modes.
#
@@ -1819,7 +1847,7 @@
'data': [ 'none', 'constant', 'cached', 'all' ] }
##
-# @Qcow2OverlapCheckFlags
+# @Qcow2OverlapCheckFlags:
#
# Structure of flags for each metadata structure. Setting a field to 'true'
# makes qemu guard that structure against unintended overwriting. The default
@@ -1842,7 +1870,7 @@
'*inactive-l2': 'bool' } }
##
-# @Qcow2OverlapChecks
+# @Qcow2OverlapChecks:
#
# Specifies which metadata structures should be guarded against unintended
# overwriting.
@@ -1859,7 +1887,7 @@
'mode': 'Qcow2OverlapCheckMode' } }
##
-# @BlockdevOptionsQcow2
+# @BlockdevOptionsQcow2:
#
# Driver specific block device options for qcow2.
#
@@ -1909,7 +1937,7 @@
##
-# @BlockdevOptionsArchipelago
+# @BlockdevOptionsArchipelago:
#
# Driver specific block device options for Archipelago.
#
@@ -1937,9 +1965,28 @@
'*vport': 'int',
'*segment': 'str' } }
+##
+# @BlockdevOptionsSsh:
+#
+# @server: host address
+#
+# @path: path to the image on the host
+#
+# @user: #optional user as which to connect, defaults to current
+# local user name
+#
+# TODO: Expose the host_key_check option in QMP
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsSsh',
+ 'data': { 'server': 'InetSocketAddress',
+ 'path': 'str',
+ '*user': 'str' } }
+
##
-# @BlkdebugEvent
+# @BlkdebugEvent:
#
# Trigger events supported by blkdebug.
#
@@ -1962,7 +2009,7 @@
'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] }
##
-# @BlkdebugInjectErrorOptions
+# @BlkdebugInjectErrorOptions:
#
# Describes a single error injection for blkdebug.
#
@@ -1994,7 +2041,7 @@
'*immediately': 'bool' } }
##
-# @BlkdebugSetStateOptions
+# @BlkdebugSetStateOptions:
#
# Describes a single state-change event for blkdebug.
#
@@ -2014,7 +2061,7 @@
'new_state': 'int' } }
##
-# @BlockdevOptionsBlkdebug
+# @BlockdevOptionsBlkdebug:
#
# Driver specific block device options for blkdebug.
#
@@ -2039,7 +2086,7 @@
'*set-state': ['BlkdebugSetStateOptions'] } }
##
-# @BlockdevOptionsBlkverify
+# @BlockdevOptionsBlkverify:
#
# Driver specific block device options for blkverify.
#
@@ -2054,7 +2101,7 @@
'raw': 'BlockdevRef' } }
##
-# @QuorumReadPattern
+# @QuorumReadPattern:
#
# An enumeration of quorum read patterns.
#
@@ -2067,7 +2114,7 @@
{ 'enum': 'QuorumReadPattern', 'data': [ 'quorum', 'fifo' ] }
##
-# @BlockdevOptionsQuorum
+# @BlockdevOptionsQuorum:
#
# Driver specific block device options for Quorum
#
@@ -2094,7 +2141,7 @@
'*read-pattern': 'QuorumReadPattern' } }
##
-# @GlusterTransport
+# @GlusterTransport:
#
# An enumeration of Gluster transport types
#
@@ -2109,7 +2156,7 @@
##
-# @GlusterServer
+# @GlusterServer:
#
# Captures the address of a socket
#
@@ -2117,9 +2164,17 @@
#
# @type: Transport type used for gluster connection
#
-# @unix: socket file
+# This is similar to SocketAddress, only distinction:
+#
+# 1. GlusterServer is a flat union, SocketAddress is a simple union.
+# A flat union is nicer than simple because it avoids nesting
+# (i.e. more {}) on the wire.
+#
+# 2. GlusterServer lacks case 'fd', since gluster doesn't let you
+# pass in a file descriptor.
#
-# @tcp: host address and port number
+# GlusterServer is actually not Gluster-specific, its a
+# compatibility evolved into an alternate for SocketAddress.
#
# Since: 2.7
##
@@ -2130,7 +2185,7 @@
'tcp': 'InetSocketAddress' } }
##
-# @BlockdevOptionsGluster
+# @BlockdevOptionsGluster:
#
# Driver specific block device options for Gluster
#
@@ -2140,7 +2195,10 @@
#
# @server: gluster servers description
#
-# @debug-level: #optional libgfapi log level (default '4' which is Error)
+# @debug: #optional libgfapi log level (default '4' which is Error)
+# (Since 2.8)
+#
+# @logfile: #optional libgfapi log file (default /dev/stderr) (Since 2.8)
#
# Since: 2.7
##
@@ -2148,25 +2206,163 @@
'data': { 'volume': 'str',
'path': 'str',
'server': ['GlusterServer'],
- '*debug-level': 'int' } }
+ '*debug': 'int',
+ '*logfile': 'str' } }
+
+##
+# @ReplicationMode:
+#
+# An enumeration of replication modes.
+#
+# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
+#
+# @secondary: Secondary mode, receive the vm's state from primary QEMU.
+#
+# Since: 2.8
+##
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+
+##
+# @BlockdevOptionsReplication:
+#
+# Driver specific block device options for replication
+#
+# @mode: the replication mode
+#
+# @top-id: #optional In secondary mode, node name or device ID of the root
+# node who owns the replication node chain. Must not be given in
+# primary mode.
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsReplication',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { 'mode': 'ReplicationMode',
+ '*top-id': 'str' } }
+
+##
+# @NFSTransport:
+#
+# An enumeration of NFS transport types
+#
+# @inet: TCP transport
+#
+# Since: 2.8
+##
+{ 'enum': 'NFSTransport',
+ 'data': [ 'inet' ] }
+
+##
+# @NFSServer:
+#
+# Captures the address of the socket
+#
+# @type: transport type used for NFS (only TCP supported)
+#
+# @host: host address for NFS server
+#
+# Since: 2.8
+##
+{ 'struct': 'NFSServer',
+ 'data': { 'type': 'NFSTransport',
+ 'host': 'str' } }
+
+##
+# @BlockdevOptionsNfs:
+#
+# Driver specific block device option for NFS
+#
+# @server: host address
+#
+# @path: path of the image on the host
+#
+# @user: #optional UID value to use when talking to the
+# server (defaults to 65534 on Windows and getuid()
+# on unix)
+#
+# @group: #optional GID value to use when talking to the
+# server (defaults to 65534 on Windows and getgid()
+# in unix)
+#
+# @tcp-syn-count: #optional number of SYNs during the session
+# establishment (defaults to libnfs default)
+#
+# @readahead-size: #optional set the readahead size in bytes (defaults
+# to libnfs default)
+#
+# @page-cache-size: #optional set the pagecache size in bytes (defaults
+# to libnfs default)
+#
+# @debug: #optional set the NFS debug level (max 2) (defaults
+# to libnfs default)
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsNfs',
+ 'data': { 'server': 'NFSServer',
+ 'path': 'str',
+ '*user': 'int',
+ '*group': 'int',
+ '*tcp-syn-count': 'int',
+ '*readahead-size': 'int',
+ '*page-cache-size': 'int',
+ '*debug': 'int' } }
+
+##
+# @BlockdevOptionsCurl:
+#
+# Driver specific block device options for the curl backend.
+#
+# @filename: path to the image file
+#
+# Since: 1.7
+##
+{ 'struct': 'BlockdevOptionsCurl',
+ 'data': { 'filename': 'str' } }
+
+##
+# @BlockdevOptionsNbd:
+#
+# Driver specific block device options for NBD.
+#
+# @server: NBD server address
+#
+# @export: #optional export name
+#
+# @tls-creds: #optional TLS credentials ID
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsNbd',
+ 'data': { 'server': 'SocketAddress',
+ '*export': 'str',
+ '*tls-creds': 'str' } }
##
-# @BlockdevOptions
+# @BlockdevOptionsRaw:
+#
+# Driver specific block device options for the raw driver.
+#
+# @offset: #optional position where the block device starts
+# @size: #optional the assumed size of the device
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsRaw',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*offset': 'int', '*size': 'int' } }
+
+##
+# @BlockdevOptions:
#
# Options for creating a block device. Many options are available for all
# block devices, independent of the block driver:
#
# @driver: block driver name
-# @id: #optional id by which the new block device can be referred to.
-# This option is only allowed on the top level of blockdev-add.
-# A BlockBackend will be created by blockdev-add if and only if
-# this option is given.
-# @node-name: #optional the name of a block driver state node (Since 2.0).
-# This option is required on the top level of blockdev-add if
-# the @id option is not given there.
+# @node-name: #optional the node name of the new node (Since 2.0).
+# This option is required on the top level of blockdev-add.
# @discard: #optional discard-related options (default: ignore)
# @cache: #optional cache-related options
-# @aio: #optional AIO backend (default: threads)
# @read-only: #optional whether the block device should be read-only
# (default: false)
# @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
@@ -2178,12 +2374,9 @@
##
{ 'union': 'BlockdevOptions',
'base': { 'driver': 'BlockdevDriver',
-# TODO 'id' is a BB-level option, remove it
- '*id': 'str',
'*node-name': 'str',
'*discard': 'BlockdevDiscardOptions',
'*cache': 'BlockdevCacheOptions',
- '*aio': 'BlockdevAioOptions',
'*read-only': 'bool',
'*detect-zeroes': 'BlockdevDetectZeroesOptions' },
'discriminator': 'driver',
@@ -2195,17 +2388,17 @@
'cloop': 'BlockdevOptionsGenericFormat',
'dmg': 'BlockdevOptionsGenericFormat',
'file': 'BlockdevOptionsFile',
- 'ftp': 'BlockdevOptionsFile',
- 'ftps': 'BlockdevOptionsFile',
+ 'ftp': 'BlockdevOptionsCurl',
+ 'ftps': 'BlockdevOptionsCurl',
'gluster': 'BlockdevOptionsGluster',
'host_cdrom': 'BlockdevOptionsFile',
'host_device':'BlockdevOptionsFile',
- 'http': 'BlockdevOptionsFile',
- 'https': 'BlockdevOptionsFile',
+ 'http': 'BlockdevOptionsCurl',
+ 'https': 'BlockdevOptionsCurl',
# TODO iscsi: Wait for structured options
'luks': 'BlockdevOptionsLUKS',
-# TODO nbd: Should take InetSocketAddress for 'host'?
-# TODO nfs: Wait for structured options
+ 'nbd': 'BlockdevOptionsNbd',
+ 'nfs': 'BlockdevOptionsNfs',
'null-aio': 'BlockdevOptionsNull',
'null-co': 'BlockdevOptionsNull',
'parallels': 'BlockdevOptionsGenericFormat',
@@ -2213,11 +2406,11 @@
'qcow': 'BlockdevOptionsGenericCOWFormat',
'qed': 'BlockdevOptionsGenericCOWFormat',
'quorum': 'BlockdevOptionsQuorum',
- 'raw': 'BlockdevOptionsGenericFormat',
+ 'raw': 'BlockdevOptionsRaw',
# TODO rbd: Wait for structured options
+ 'replication':'BlockdevOptionsReplication',
# TODO sheepdog: Wait for structured options
-# TODO ssh: Should take InetSocketAddress for 'host'?
- 'tftp': 'BlockdevOptionsFile',
+ 'ssh': 'BlockdevOptionsSsh',
'vdi': 'BlockdevOptionsGenericFormat',
'vhdx': 'BlockdevOptionsGenericFormat',
'vmdk': 'BlockdevOptionsGenericCOWFormat',
@@ -2226,7 +2419,7 @@
} }
##
-# @BlockdevRef
+# @BlockdevRef:
#
# Reference to a block device.
#
@@ -2252,39 +2445,28 @@
# block drivers among other things. Stay away from it unless you want
# to help with its development.
#
-# @options: block device options for the new device
+# For the arguments, see the documentation of BlockdevOptions.
#
# Since: 1.7
##
-{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
+{ 'command': 'blockdev-add', 'data': 'BlockdevOptions', 'boxed': true }
##
# @x-blockdev-del:
#
# Deletes a block device that has been added using blockdev-add.
-# The selected device can be either a block backend or a graph node.
-#
-# In the former case the backend will be destroyed, along with its
-# inserted medium if there's any. The command will fail if the backend
-# or its medium are in use.
-#
-# In the latter case the node will be destroyed. The command will fail
-# if the node is attached to a block backend or is otherwise being
-# used.
-#
-# One of @id or @node-name must be specified, but not both.
+# The command will fail if the node is attached to a device or is
+# otherwise being used.
#
# This command is still a work in progress and is considered
# experimental. Stay away from it unless you want to help with its
# development.
#
-# @id: #optional Name of the block backend device to delete.
-#
-# @node-name: #optional Name of the graph node to delete.
+# @node-name: Name of the graph node to delete.
#
# Since: 2.5
##
-{ 'command': 'x-blockdev-del', 'data': { '*id': 'str', '*node-name': 'str' } }
+{ 'command': 'x-blockdev-del', 'data': { 'node-name': 'str' } }
##
# @blockdev-open-tray:
@@ -2304,7 +2486,9 @@
# to it
# - if the guest device does not have an actual tray
#
-# @device: block device name
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @force: #optional if false (the default), an eject request will be sent to
# the guest if it has locked the tray (and the tray will not be opened
@@ -2314,7 +2498,8 @@
# Since: 2.5
##
{ 'command': 'blockdev-open-tray',
- 'data': { 'device': 'str',
+ 'data': { '*device': 'str',
+ '*id': 'str',
'*force': 'bool' } }
##
@@ -2326,12 +2511,15 @@
#
# If the tray was already closed before, this will be a no-op.
#
-# @device: block device name
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# Since: 2.5
##
{ 'command': 'blockdev-close-tray',
- 'data': { 'device': 'str' } }
+ 'data': { '*device': 'str',
+ '*id': 'str' } }
##
# @x-blockdev-remove-medium:
@@ -2345,12 +2533,15 @@
# This command is still a work in progress and is considered experimental.
# Stay away from it unless you want to help with its development.
#
-# @device: block device name
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# Since: 2.5
##
{ 'command': 'x-blockdev-remove-medium',
- 'data': { 'device': 'str' } }
+ 'data': { '*device': 'str',
+ '*id': 'str' } }
##
# @x-blockdev-insert-medium:
@@ -2362,14 +2553,17 @@
# This command is still a work in progress and is considered experimental.
# Stay away from it unless you want to help with its development.
#
-# @device: block device name
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @node-name: name of a node in the block driver state graph
#
# Since: 2.5
##
{ 'command': 'x-blockdev-insert-medium',
- 'data': { 'device': 'str',
+ 'data': { '*device': 'str',
+ '*id': 'str',
'node-name': 'str'} }
@@ -2399,7 +2593,10 @@
# combines blockdev-open-tray, x-blockdev-remove-medium,
# x-blockdev-insert-medium and blockdev-close-tray).
#
-# @device: block device name
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device
+# (since: 2.8)
#
# @filename: filename of the new image to be loaded
#
@@ -2412,14 +2609,15 @@
# Since: 2.5
##
{ 'command': 'blockdev-change-medium',
- 'data': { 'device': 'str',
+ 'data': { '*device': 'str',
+ '*id': 'str',
'filename': 'str',
'*format': 'str',
'*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
##
-# @BlockErrorAction
+# @BlockErrorAction:
#
# An enumeration of action that has been taken when a DISK I/O occurs
#
@@ -2436,7 +2634,7 @@
##
-# @BLOCK_IMAGE_CORRUPTED
+# @BLOCK_IMAGE_CORRUPTED:
#
# Emitted when a corruption has been detected in a disk image
#
@@ -2471,11 +2669,17 @@
'fatal' : 'bool' } }
##
-# @BLOCK_IO_ERROR
+# @BLOCK_IO_ERROR:
#
# Emitted when a disk I/O error occurs
#
-# @device: device name
+# @device: device name. This is always present for compatibility
+# reasons, but it can be empty ("") if the image does not
+# have a device name associated.
+#
+# @node-name: node name. Note that errors may be reported for the root node
+# that is directly attached to a guest device rather than for the
+# node where the error occurred. (Since: 2.8)
#
# @operation: I/O operation
#
@@ -2496,12 +2700,12 @@
# Since: 0.13.0
##
{ 'event': 'BLOCK_IO_ERROR',
- 'data': { 'device': 'str', 'operation': 'IoOperationType',
+ 'data': { 'device': 'str', 'node-name': 'str', 'operation': 'IoOperationType',
'action': 'BlockErrorAction', '*nospace': 'bool',
'reason': 'str' } }
##
-# @BLOCK_JOB_COMPLETED
+# @BLOCK_JOB_COMPLETED:
#
# Emitted when a block job has completed
#
@@ -2533,7 +2737,7 @@
'*error': 'str' } }
##
-# @BLOCK_JOB_CANCELLED
+# @BLOCK_JOB_CANCELLED:
#
# Emitted when a block job has been cancelled
#
@@ -2559,7 +2763,7 @@
'speed' : 'int' } }
##
-# @BLOCK_JOB_ERROR
+# @BLOCK_JOB_ERROR:
#
# Emitted when a block job encounters an error
#
@@ -2578,7 +2782,7 @@
'action' : 'BlockErrorAction' } }
##
-# @BLOCK_JOB_READY
+# @BLOCK_JOB_READY:
#
# Emitted when a block job is ready to complete
#
@@ -2606,7 +2810,8 @@
'offset': 'int',
'speed' : 'int' } }
-# @PreallocMode
+##
+# @PreallocMode:
#
# Preallocation mode of QEMU image file
#
@@ -2618,13 +2823,13 @@
# space is really available. @full preallocation also sets up
# metadata correctly.
#
-# Since 2.2
+# Since: 2.2
##
{ 'enum': 'PreallocMode',
'data': [ 'off', 'metadata', 'falloc', 'full' ] }
##
-# @BLOCK_WRITE_THRESHOLD
+# @BLOCK_WRITE_THRESHOLD:
#
# Emitted when writes on block device reaches or exceeds the
# configured write threshold. For thin-provisioned devices, this
@@ -2647,7 +2852,7 @@
'write-threshold': 'uint64' } }
##
-# @block-set-write-threshold
+# @block-set-write-threshold:
#
# Change the write threshold for a block drive. An event will be delivered
# if a write to this block drive crosses the configured threshold.
@@ -2665,7 +2870,7 @@
'data': { 'node-name': 'str', 'write-threshold': 'uint64' } }
##
-# @x-blockdev-change
+# @x-blockdev-change:
#
# Dynamically reconfigure the block driver state graph. It can be used
# to add, remove, insert or replace a graph node. Currently only the
diff --git a/qapi/block.json b/qapi/block.json
index 937337dce5..8e9f59019a 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -40,7 +40,7 @@
'data': ['auto', 'none', 'lba', 'large', 'rechs']}
##
-# @FloppyDriveType
+# @FloppyDriveType:
#
# Type of Floppy drive to be emulated by the Floppy Disk Controller.
#
@@ -56,9 +56,10 @@
'data': ['144', '288', '120', 'none', 'auto']}
##
-# @BlockdevSnapshotInternal
+# @BlockdevSnapshotInternal:
#
-# @device: the name of the device to generate the snapshot from
+# @device: the device name or node-name of a root node to generate the snapshot
+# from
#
# @name: the name of the internal snapshot to be created
#
@@ -72,7 +73,7 @@
'data': { 'device': 'str', 'name': 'str' } }
##
-# @blockdev-snapshot-internal-sync
+# @blockdev-snapshot-internal-sync:
#
# Synchronously take an internal snapshot of a block device, when the format
# of the image used supports it.
@@ -80,39 +81,40 @@
# For the arguments, see the documentation of BlockdevSnapshotInternal.
#
# Returns: nothing on success
-# If @device is not a valid block device, DeviceNotFound
+# If @device is not a valid block device, GenericError
# If any snapshot matching @name exists, or @name is empty,
# GenericError
# If the format of the image used does not support it,
# BlockFormatFeatureNotSupported
#
-# Since 1.7
+# Since: 1.7
##
{ 'command': 'blockdev-snapshot-internal-sync',
'data': 'BlockdevSnapshotInternal' }
##
-# @blockdev-snapshot-delete-internal-sync
+# @blockdev-snapshot-delete-internal-sync:
#
# Synchronously delete an internal snapshot of a block device, when the format
# of the image used support it. The snapshot is identified by name or id or
# both. One of the name or id is required. Return SnapshotInfo for the
# successfully deleted snapshot.
#
-# @device: the name of the device to delete the snapshot from
+# @device: the device name or node-name of a root node to delete the snapshot
+# from
#
# @id: optional the snapshot's ID to be deleted
#
# @name: optional the snapshot's name to be deleted
#
# Returns: SnapshotInfo on success
-# If @device is not a valid block device, DeviceNotFound
+# If @device is not a valid block device, GenericError
# If snapshot not found, GenericError
# If the format of the image used does not support it,
# BlockFormatFeatureNotSupported
# If @id and @name are both not specified, GenericError
#
-# Since 1.7
+# Since: 1.7
##
{ 'command': 'blockdev-snapshot-delete-internal-sync',
'data': { 'device': 'str', '*id': 'str', '*name': 'str'},
@@ -123,7 +125,9 @@
#
# Ejects a device from a removable drive.
#
-# @device: The name of the device
+# @device: #optional Block device name (deprecated, use @id instead)
+#
+# @id: #optional The name or QOM path of the guest device (since: 2.8)
#
# @force: @optional If true, eject regardless of whether the drive is locked.
# If not specified, the default value is false.
@@ -135,7 +139,10 @@
#
# Since: 0.14.0
##
-{ 'command': 'eject', 'data': {'device': 'str', '*force': 'bool'} }
+{ 'command': 'eject',
+ 'data': { '*device': 'str',
+ '*id': 'str',
+ '*force': 'bool' } }
##
# @nbd-server-start:
@@ -159,9 +166,9 @@
##
# @nbd-server-add:
#
-# Export a device to QEMU's embedded NBD server.
+# Export a block node to QEMU's embedded NBD server.
#
-# @device: Block device to be exported
+# @device: The device name or node name of the node to be exported
#
# @writable: Whether clients should be able to write to the device via the
# NBD connection (default false). #optional
@@ -183,22 +190,26 @@
{ 'command': 'nbd-server-stop' }
##
-# @DEVICE_TRAY_MOVED
+# @DEVICE_TRAY_MOVED:
#
# Emitted whenever the tray of a removable device is moved by the guest or by
# HMP/QMP commands
#
-# @device: device name
+# @device: Block device name. This is always present for compatibility
+# reasons, but it can be empty ("") if the image does not
+# have a device name associated.
+#
+# @id: The name or QOM path of the guest device (since 2.8)
#
# @tray-open: true if the tray has been opened or false if it has been closed
#
# Since: 1.1
##
{ 'event': 'DEVICE_TRAY_MOVED',
- 'data': { 'device': 'str', 'tray-open': 'bool' } }
+ 'data': { 'device': 'str', 'id': 'str', 'tray-open': 'bool' } }
##
-# @QuorumOpType
+# @QuorumOpType:
#
# An enumeration of the quorum operation types
#
diff --git a/qapi/common.json b/qapi/common.json
index 9353a7b377..624a8619c8 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -3,7 +3,7 @@
# QAPI common definitions
##
-# @QapiErrorClass
+# @QapiErrorClass:
#
# QEMU error classes
#
@@ -30,15 +30,15 @@
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
##
-# @VersionTriple
+# @VersionTriple:
#
# A three-part version number.
#
-# @qemu.major: The major version number.
+# @major: The major version number.
#
-# @qemu.minor: The minor version number.
+# @minor: The minor version number.
#
-# @qemu.micro: The micro version number.
+# @micro: The micro version number.
#
# Since: 2.4
##
@@ -101,7 +101,7 @@
{ 'command': 'query-commands', 'returns': ['CommandInfo'] }
##
-# @OnOffAuto
+# @OnOffAuto:
#
# An enumeration of three options: on, off, and auto
#
@@ -117,7 +117,7 @@
'data': [ 'auto', 'on', 'off' ] }
##
-# @OnOffSplit
+# @OnOffSplit:
#
# An enumeration of three values: on, off, and split
#
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 34d2583154..15d296e3c1 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -3,7 +3,7 @@
# QAPI crypto definitions
##
-# QCryptoTLSCredsEndpoint:
+# @QCryptoTLSCredsEndpoint:
#
# The type of network endpoint that will be using the credentials.
# Most types of credential require different setup / structures
@@ -22,7 +22,7 @@
##
-# QCryptoSecretFormat:
+# @QCryptoSecretFormat:
#
# The data format that the secret is provided in
#
@@ -36,7 +36,7 @@
##
-# QCryptoHashAlgorithm:
+# @QCryptoHashAlgorithm:
#
# The supported algorithms for computing content digests
#
@@ -55,7 +55,7 @@
##
-# QCryptoCipherAlgorithm:
+# @QCryptoCipherAlgorithm:
#
# The supported algorithms for content encryption ciphers
#
@@ -82,22 +82,23 @@
##
-# QCryptoCipherMode:
+# @QCryptoCipherMode:
#
# The supported modes for content encryption ciphers
#
# @ecb: Electronic Code Book
# @cbc: Cipher Block Chaining
# @xts: XEX with tweaked code book and ciphertext stealing
+# @ctr: Counter (Since 2.8)
# Since: 2.6
##
{ 'enum': 'QCryptoCipherMode',
'prefix': 'QCRYPTO_CIPHER_MODE',
- 'data': ['ecb', 'cbc', 'xts']}
+ 'data': ['ecb', 'cbc', 'xts', 'ctr']}
##
-# QCryptoIVGenAlgorithm:
+# @QCryptoIVGenAlgorithm:
#
# The supported algorithms for generating initialization
# vectors for full disk encryption. The 'plain' generator
@@ -115,7 +116,7 @@
'data': ['plain', 'plain64', 'essiv']}
##
-# QCryptoBlockFormat:
+# @QCryptoBlockFormat:
#
# The supported full disk encryption formats
#
@@ -130,7 +131,7 @@
'data': ['qcow', 'luks']}
##
-# QCryptoBlockOptionsBase:
+# @QCryptoBlockOptionsBase:
#
# The common options that apply to all full disk
# encryption formats
@@ -143,7 +144,7 @@
'data': { 'format': 'QCryptoBlockFormat' }}
##
-# QCryptoBlockOptionsQCow:
+# @QCryptoBlockOptionsQCow:
#
# The options that apply to QCow/QCow2 AES-CBC encryption format
#
@@ -157,7 +158,7 @@
'data': { '*key-secret': 'str' }}
##
-# QCryptoBlockOptionsLUKS:
+# @QCryptoBlockOptionsLUKS:
#
# The options that apply to LUKS encryption format
#
@@ -171,7 +172,7 @@
##
-# QCryptoBlockCreateOptionsLUKS:
+# @QCryptoBlockCreateOptionsLUKS:
#
# The options that apply to LUKS encryption format initialization
#
@@ -185,6 +186,9 @@
# Currently defaults to 'sha256'
# @hash-alg: #optional the master key hash algorithm
# Currently defaults to 'sha256'
+# @iter-time: #optional number of milliseconds to spend in
+# PBKDF passphrase processing. Currently defaults
+# to 2000. (since 2.8)
# Since: 2.6
##
{ 'struct': 'QCryptoBlockCreateOptionsLUKS',
@@ -193,11 +197,12 @@
'*cipher-mode': 'QCryptoCipherMode',
'*ivgen-alg': 'QCryptoIVGenAlgorithm',
'*ivgen-hash-alg': 'QCryptoHashAlgorithm',
- '*hash-alg': 'QCryptoHashAlgorithm'}}
+ '*hash-alg': 'QCryptoHashAlgorithm',
+ '*iter-time': 'int'}}
##
-# QCryptoBlockOpenOptions:
+# @QCryptoBlockOpenOptions:
#
# The options that are available for all encryption formats
# when opening an existing volume
@@ -212,7 +217,7 @@
##
-# QCryptoBlockCreateOptions:
+# @QCryptoBlockCreateOptions:
#
# The options that are available for all encryption formats
# when initializing a new volume
@@ -227,7 +232,7 @@
##
-# QCryptoBlockInfoBase:
+# @QCryptoBlockInfoBase:
#
# The common information that applies to all full disk
# encryption formats
@@ -241,7 +246,7 @@
##
-# QCryptoBlockInfoLUKSSlot:
+# @QCryptoBlockInfoLUKSSlot:
#
# Information about the LUKS block encryption key
# slot options
@@ -261,7 +266,7 @@
##
-# QCryptoBlockInfoLUKS:
+# @QCryptoBlockInfoLUKS:
#
# Information about the LUKS block encryption options
#
@@ -289,7 +294,7 @@
'slots': [ 'QCryptoBlockInfoLUKSSlot' ] }}
##
-# QCryptoBlockInfoQCow:
+# @QCryptoBlockInfoQCow:
#
# Information about the QCow block encryption options
#
@@ -300,7 +305,7 @@
##
-# QCryptoBlockInfo:
+# @QCryptoBlockInfo:
#
# Information about the block encryption options
#
diff --git a/qapi/event.json b/qapi/event.json
index 8642052ebc..37bf34ed6d 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -1,5 +1,5 @@
##
-# @SHUTDOWN
+# @SHUTDOWN:
#
# Emitted when the virtual machine has shut down, indicating that qemu is
# about to exit.
@@ -12,7 +12,7 @@
{ 'event': 'SHUTDOWN' }
##
-# @POWERDOWN
+# @POWERDOWN:
#
# Emitted when the virtual machine is powered down through the power control
# system, such as via ACPI.
@@ -22,7 +22,7 @@
{ 'event': 'POWERDOWN' }
##
-# @RESET
+# @RESET:
#
# Emitted when the virtual machine is reset
#
@@ -31,7 +31,7 @@
{ 'event': 'RESET' }
##
-# @STOP
+# @STOP:
#
# Emitted when the virtual machine is stopped
#
@@ -40,7 +40,7 @@
{ 'event': 'STOP' }
##
-# @RESUME
+# @RESUME:
#
# Emitted when the virtual machine resumes execution
#
@@ -49,7 +49,7 @@
{ 'event': 'RESUME' }
##
-# @SUSPEND
+# @SUSPEND:
#
# Emitted when guest enters a hardware suspension state, for example, S3 state,
# which is sometimes called standby state
@@ -59,7 +59,7 @@
{ 'event': 'SUSPEND' }
##
-# @SUSPEND_DISK
+# @SUSPEND_DISK:
#
# Emitted when guest enters a hardware suspension state with data saved on
# disk, for example, S4 state, which is sometimes called hibernate state
@@ -71,7 +71,7 @@
{ 'event': 'SUSPEND_DISK' }
##
-# @WAKEUP
+# @WAKEUP:
#
# Emitted when the guest has woken up from suspend state and is running
#
@@ -80,7 +80,7 @@
{ 'event': 'WAKEUP' }
##
-# @RTC_CHANGE
+# @RTC_CHANGE:
#
# Emitted when the guest changes the RTC time.
#
@@ -93,7 +93,7 @@
'data': { 'offset': 'int' } }
##
-# @WATCHDOG
+# @WATCHDOG:
#
# Emitted when the watchdog device's timer is expired
#
@@ -108,7 +108,7 @@
'data': { 'action': 'WatchdogExpirationAction' } }
##
-# @DEVICE_DELETED
+# @DEVICE_DELETED:
#
# Emitted whenever the device removal completion is acknowledged by the guest.
# At this point, it's safe to reuse the specified device ID. Device removal can
@@ -124,7 +124,7 @@
'data': { '*device': 'str', 'path': 'str' } }
##
-# @NIC_RX_FILTER_CHANGED
+# @NIC_RX_FILTER_CHANGED:
#
# Emitted once until the 'query-rx-filter' command is executed, the first event
# will always be emitted
@@ -139,7 +139,7 @@
'data': { '*name': 'str', 'path': 'str' } }
##
-# @VNC_CONNECTED
+# @VNC_CONNECTED:
#
# Emitted when a VNC client establishes a connection
#
@@ -157,7 +157,7 @@
'client': 'VncBasicInfo' } }
##
-# @VNC_INITIALIZED
+# @VNC_INITIALIZED:
#
# Emitted after authentication takes place (if any) and the VNC session is
# made active
@@ -173,7 +173,7 @@
'client': 'VncClientInfo' } }
##
-# @VNC_DISCONNECTED
+# @VNC_DISCONNECTED:
#
# Emitted when the connection is closed
#
@@ -188,7 +188,7 @@
'client': 'VncClientInfo' } }
##
-# @SPICE_CONNECTED
+# @SPICE_CONNECTED:
#
# Emitted when a SPICE client establishes a connection
#
@@ -203,7 +203,7 @@
'client': 'SpiceBasicInfo' } }
##
-# @SPICE_INITIALIZED
+# @SPICE_INITIALIZED:
#
# Emitted after initial handshake and authentication takes place (if any)
# and the SPICE channel is up and running
@@ -219,7 +219,7 @@
'client': 'SpiceChannel' } }
##
-# @SPICE_DISCONNECTED
+# @SPICE_DISCONNECTED:
#
# Emitted when the SPICE connection is closed
#
@@ -234,7 +234,7 @@
'client': 'SpiceBasicInfo' } }
##
-# @SPICE_MIGRATE_COMPLETED
+# @SPICE_MIGRATE_COMPLETED:
#
# Emitted when SPICE migration has completed
#
@@ -243,7 +243,7 @@
{ 'event': 'SPICE_MIGRATE_COMPLETED' }
##
-# @MIGRATION
+# @MIGRATION:
#
# Emitted when a migration event happens
#
@@ -255,7 +255,7 @@
'data': {'status': 'MigrationStatus'}}
##
-# @MIGRATION_PASS
+# @MIGRATION_PASS:
#
# Emitted from the source side of a migration at the start of each pass
# (when it syncs the dirty bitmap)
@@ -268,7 +268,7 @@
'data': { 'pass': 'int' } }
##
-# @ACPI_DEVICE_OST
+# @ACPI_DEVICE_OST:
#
# Emitted when guest executes ACPI _OST method.
#
@@ -280,7 +280,7 @@
'data': { 'info': 'ACPIOSTInfo' } }
##
-# @BALLOON_CHANGE
+# @BALLOON_CHANGE:
#
# Emitted when the guest changes the actual BALLOON level. This value is
# equivalent to the @actual field return by the 'query-balloon' command
@@ -293,7 +293,7 @@
'data': { 'actual': 'int' } }
##
-# @GUEST_PANICKED
+# @GUEST_PANICKED:
#
# Emitted when guest OS panic is detected
#
@@ -305,7 +305,7 @@
'data': { 'action': 'GuestPanicAction' } }
##
-# @QUORUM_FAILURE
+# @QUORUM_FAILURE:
#
# Emitted by the Quorum block driver if it fails to establish a quorum
#
@@ -321,7 +321,7 @@
'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
##
-# @QUORUM_REPORT_BAD
+# @QUORUM_REPORT_BAD:
#
# Emitted to report a corruption of a Quorum file
#
@@ -345,7 +345,7 @@
'sector-num': 'int', 'sectors-count': 'int' } }
##
-# @VSERPORT_CHANGE
+# @VSERPORT_CHANGE:
#
# Emitted when the guest opens or closes a virtio-serial port.
#
@@ -359,7 +359,7 @@
'data': { 'id': 'str', 'open': 'bool' } }
##
-# @MEM_UNPLUG_ERROR
+# @MEM_UNPLUG_ERROR:
#
# Emitted when memory hot unplug error occurs.
#
@@ -373,7 +373,7 @@
'data': { 'device': 'str', 'msg': 'str' } }
##
-# @DUMP_COMPLETED
+# @DUMP_COMPLETED:
#
# Emitted when background dump has completed
#
diff --git a/qapi/introspect.json b/qapi/introspect.json
index 3fd81fb540..fd4dc84196 100644
--- a/qapi/introspect.json
+++ b/qapi/introspect.json
@@ -11,7 +11,7 @@
# See the COPYING file in the top-level directory.
##
-# @query-qmp-schema
+# @query-qmp-schema:
#
# Command query-qmp-schema exposes the QMP wire ABI as an array of
# SchemaInfo. This lets QMP clients figure out what commands and
@@ -49,7 +49,7 @@
'gen': false } # just to simplify qmp_query_json()
##
-# @SchemaMetaType
+# @SchemaMetaType:
#
# This is a @SchemaInfo's meta type, i.e. the kind of entity it
# describes.
@@ -75,7 +75,7 @@
'command', 'event' ] }
##
-# @SchemaInfo
+# @SchemaInfo:
#
# @name: the entity's name, inherited from @base.
# Commands and events have the name defined in the QAPI schema.
@@ -105,7 +105,7 @@
'event': 'SchemaInfoEvent' } }
##
-# @SchemaInfoBuiltin
+# @SchemaInfoBuiltin:
#
# Additional SchemaInfo members for meta-type 'builtin'.
#
@@ -117,7 +117,7 @@
'data': { 'json-type': 'JSONType' } }
##
-# @JSONType
+# @JSONType:
#
# The four primitive and two structured types according to RFC 7159
# section 1, plus 'int' (split off 'number'), plus the obvious top
@@ -130,7 +130,7 @@
'object', 'array', 'value' ] }
##
-# @SchemaInfoEnum
+# @SchemaInfoEnum:
#
# Additional SchemaInfo members for meta-type 'enum'.
#
@@ -144,7 +144,7 @@
'data': { 'values': ['str'] } }
##
-# @SchemaInfoArray
+# @SchemaInfoArray:
#
# Additional SchemaInfo members for meta-type 'array'.
#
@@ -158,7 +158,7 @@
'data': { 'element-type': 'str' } }
##
-# @SchemaInfoObject
+# @SchemaInfoObject:
#
# Additional SchemaInfo members for meta-type 'object'.
#
@@ -183,7 +183,7 @@
'*variants': [ 'SchemaInfoObjectVariant' ] } }
##
-# @SchemaInfoObjectMember
+# @SchemaInfoObjectMember:
#
# An object member.
#
@@ -206,7 +206,7 @@
# @default's type must be null or match @type
##
-# @SchemaInfoObjectVariant
+# @SchemaInfoObjectVariant:
#
# The variant members for a value of the type tag.
#
@@ -221,7 +221,7 @@
'data': { 'case': 'str', 'type': 'str' } }
##
-# @SchemaInfoAlternate
+# @SchemaInfoAlternate:
#
# Additional SchemaInfo members for meta-type 'alternate'.
#
@@ -237,7 +237,7 @@
'data': { 'members': [ 'SchemaInfoAlternateMember' ] } }
##
-# @SchemaInfoAlternateMember
+# @SchemaInfoAlternateMember:
#
# An alternate member.
#
@@ -249,7 +249,7 @@
'data': { 'type': 'str' } }
##
-# @SchemaInfoCommand
+# @SchemaInfoCommand:
#
# Additional SchemaInfo members for meta-type 'command'.
#
@@ -266,7 +266,7 @@
'data': { 'arg-type': 'str', 'ret-type': 'str' } }
##
-# @SchemaInfoEvent
+# @SchemaInfoEvent:
#
# Additional SchemaInfo members for meta-type 'event'.
#
diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c
index 0bb8216372..34086cbfc0 100644
--- a/qapi/qapi-clone-visitor.c
+++ b/qapi/qapi-clone-visitor.c
@@ -110,7 +110,7 @@ static void qapi_clone_type_str(Visitor *v, const char *name, char **obj,
assert(qcv->depth);
/*
* Pointer was already cloned by g_memdup; create fresh copy.
- * Note that as long as qmp-output-visitor accepts NULL instead of
+ * Note that as long as qobject-output-visitor accepts NULL instead of
* "", then we must do likewise. However, we want to obey the
* input visitor semantics of never producing NULL when the empty
* string is intended.
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 55f5876dc0..63bd97b341 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -19,10 +19,12 @@
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
+#include "trace.h"
void visit_complete(Visitor *v, void *opaque)
{
assert(v->type != VISITOR_OUTPUT || v->complete);
+ trace_visit_complete(v, opaque);
if (v->complete) {
v->complete(v, opaque);
}
@@ -30,6 +32,7 @@ void visit_complete(Visitor *v, void *opaque)
void visit_free(Visitor *v)
{
+ trace_visit_free(v);
if (v) {
v->free(v);
}
@@ -40,6 +43,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
{
Error *err = NULL;
+ trace_visit_start_struct(v, name, obj, size);
if (obj) {
assert(size);
assert(!(v->type & VISITOR_OUTPUT) || *obj);
@@ -53,6 +57,7 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
void visit_check_struct(Visitor *v, Error **errp)
{
+ trace_visit_check_struct(v);
if (v->check_struct) {
v->check_struct(v, errp);
}
@@ -60,6 +65,7 @@ void visit_check_struct(Visitor *v, Error **errp)
void visit_end_struct(Visitor *v, void **obj)
{
+ trace_visit_end_struct(v, obj);
v->end_struct(v, obj);
}
@@ -69,6 +75,7 @@ void visit_start_list(Visitor *v, const char *name, GenericList **list,
Error *err = NULL;
assert(!list || size >= sizeof(GenericList));
+ trace_visit_start_list(v, name, list, size);
v->start_list(v, name, list, size, &err);
if (list && (v->type & VISITOR_INPUT)) {
assert(!(err && *list));
@@ -79,11 +86,13 @@ void visit_start_list(Visitor *v, const char *name, GenericList **list,
GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
{
assert(tail && size >= sizeof(GenericList));
+ trace_visit_next_list(v, tail, size);
return v->next_list(v, tail, size);
}
void visit_end_list(Visitor *v, void **obj)
{
+ trace_visit_end_list(v, obj);
v->end_list(v, obj);
}
@@ -95,6 +104,7 @@ void visit_start_alternate(Visitor *v, const char *name,
assert(obj && size >= sizeof(GenericAlternate));
assert(!(v->type & VISITOR_OUTPUT) || *obj);
+ trace_visit_start_alternate(v, name, obj, size, promote_int);
if (v->start_alternate) {
v->start_alternate(v, name, obj, size, promote_int, &err);
}
@@ -106,6 +116,7 @@ void visit_start_alternate(Visitor *v, const char *name,
void visit_end_alternate(Visitor *v, void **obj)
{
+ trace_visit_end_alternate(v, obj);
if (v->end_alternate) {
v->end_alternate(v, obj);
}
@@ -113,6 +124,7 @@ void visit_end_alternate(Visitor *v, void **obj)
bool visit_optional(Visitor *v, const char *name, bool *present)
{
+ trace_visit_optional(v, name, present);
if (v->optional) {
v->optional(v, name, present);
}
@@ -127,6 +139,7 @@ bool visit_is_input(Visitor *v)
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
{
assert(obj);
+ trace_visit_type_int(v, name, obj);
v->type_int64(v, name, obj, errp);
}
@@ -150,7 +163,10 @@ static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint8(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
*obj = value;
}
@@ -158,7 +174,10 @@ void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint16(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
*obj = value;
}
@@ -166,7 +185,10 @@ void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint32(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
*obj = value;
}
@@ -175,6 +197,7 @@ void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
Error **errp)
{
assert(obj);
+ trace_visit_type_uint64(v, name, obj);
v->type_uint64(v, name, obj, errp);
}
@@ -198,7 +221,10 @@ static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int8(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
*obj = value;
}
@@ -206,7 +232,10 @@ void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int16(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
*obj = value;
}
@@ -214,7 +243,10 @@ void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int32(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
*obj = value;
}
@@ -223,6 +255,7 @@ void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
Error **errp)
{
assert(obj);
+ trace_visit_type_int64(v, name, obj);
v->type_int64(v, name, obj, errp);
}
@@ -230,6 +263,7 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
Error **errp)
{
assert(obj);
+ trace_visit_type_size(v, name, obj);
if (v->type_size) {
v->type_size(v, name, obj, errp);
} else {
@@ -240,6 +274,7 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
{
assert(obj);
+ trace_visit_type_bool(v, name, obj);
v->type_bool(v, name, obj, errp);
}
@@ -252,6 +287,7 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
* can enable:
assert(!(v->type & VISITOR_OUTPUT) || *obj);
*/
+ trace_visit_type_str(v, name, obj);
v->type_str(v, name, obj, &err);
if (v->type & VISITOR_INPUT) {
assert(!err != !*obj);
@@ -263,6 +299,7 @@ void visit_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
assert(obj);
+ trace_visit_type_number(v, name, obj);
v->type_number(v, name, obj, errp);
}
@@ -272,6 +309,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
assert(obj);
assert(v->type != VISITOR_OUTPUT || *obj);
+ trace_visit_type_any(v, name, obj);
v->type_any(v, name, obj, &err);
if (v->type == VISITOR_INPUT) {
assert(!err != !*obj);
@@ -281,6 +319,7 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
void visit_type_null(Visitor *v, const char *name, Error **errp)
{
+ trace_visit_type_null(v, name);
v->type_null(v, name, errp);
}
diff --git a/qapi/qmp-event.c b/qapi/qmp-event.c
index 8bba165bfb..802ede48e3 100644
--- a/qapi/qmp-event.c
+++ b/qapi/qmp-event.c
@@ -35,21 +35,12 @@ static void timestamp_put(QDict *qdict)
int err;
QObject *obj;
qemu_timeval tv;
- int64_t sec, usec;
err = qemu_gettimeofday(&tv);
- if (err < 0) {
- /* Put -1 to indicate failure of getting host time */
- sec = -1;
- usec = -1;
- } else {
- sec = tv.tv_sec;
- usec = tv.tv_usec;
- }
-
- obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
- "'microseconds': %" PRId64 " }",
- sec, usec);
+ /* Put -1 to indicate failure of getting host time */
+ obj = qobject_from_jsonf("{ 'seconds': %lld, 'microseconds': %lld }",
+ err < 0 ? -1LL : (long long)tv.tv_sec,
+ err < 0 ? -1LL : (long long)tv.tv_usec);
qdict_put_obj(qdict, "timestamp", obj);
}
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
deleted file mode 100644
index 9e3b67ce13..0000000000
--- a/qapi/qmp-output-visitor.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Core Definitions for QAPI/QMP Command Registry
- *
- * Copyright (C) 2012-2016 Red Hat, Inc.
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/visitor-impl.h"
-#include "qemu/queue.h"
-#include "qemu-common.h"
-#include "qapi/qmp/types.h"
-
-typedef struct QStackEntry
-{
- QObject *value;
- void *qapi; /* sanity check that caller uses same pointer */
- QSLIST_ENTRY(QStackEntry) node;
-} QStackEntry;
-
-struct QmpOutputVisitor
-{
- Visitor visitor;
- QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
- QObject *root; /* Root of the output visit */
- QObject **result; /* User's storage location for result */
-};
-
-#define qmp_output_add(qov, name, value) \
- qmp_output_add_obj(qov, name, QOBJECT(value))
-#define qmp_output_push(qov, value, qapi) \
- qmp_output_push_obj(qov, QOBJECT(value), qapi)
-
-static QmpOutputVisitor *to_qov(Visitor *v)
-{
- return container_of(v, QmpOutputVisitor, visitor);
-}
-
-/* Push @value onto the stack of current QObjects being built */
-static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value,
- void *qapi)
-{
- QStackEntry *e = g_malloc0(sizeof(*e));
-
- assert(qov->root);
- assert(value);
- e->value = value;
- e->qapi = qapi;
- QSLIST_INSERT_HEAD(&qov->stack, e, node);
-}
-
-/* Pop a value off the stack of QObjects being built, and return it. */
-static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
-{
- QStackEntry *e = QSLIST_FIRST(&qov->stack);
- QObject *value;
-
- assert(e);
- assert(e->qapi == qapi);
- QSLIST_REMOVE_HEAD(&qov->stack, node);
- value = e->value;
- assert(value);
- g_free(e);
- return value;
-}
-
-/* Add @value to the current QObject being built.
- * If the stack is visiting a dictionary or list, @value is now owned
- * by that container. Otherwise, @value is now the root. */
-static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
- QObject *value)
-{
- QStackEntry *e = QSLIST_FIRST(&qov->stack);
- QObject *cur = e ? e->value : NULL;
-
- if (!cur) {
- /* Don't allow reuse of visitor on more than one root */
- assert(!qov->root);
- qov->root = value;
- } else {
- switch (qobject_type(cur)) {
- case QTYPE_QDICT:
- assert(name);
- qdict_put_obj(qobject_to_qdict(cur), name, value);
- break;
- case QTYPE_QLIST:
- assert(!name);
- qlist_append_obj(qobject_to_qlist(cur), value);
- break;
- default:
- g_assert_not_reached();
- }
- }
-}
-
-static void qmp_output_start_struct(Visitor *v, const char *name, void **obj,
- size_t unused, Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QDict *dict = qdict_new();
-
- qmp_output_add(qov, name, dict);
- qmp_output_push(qov, dict, obj);
-}
-
-static void qmp_output_end_struct(Visitor *v, void **obj)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QObject *value = qmp_output_pop(qov, obj);
- assert(qobject_type(value) == QTYPE_QDICT);
-}
-
-static void qmp_output_start_list(Visitor *v, const char *name,
- GenericList **listp, size_t size,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QList *list = qlist_new();
-
- qmp_output_add(qov, name, list);
- qmp_output_push(qov, list, listp);
-}
-
-static GenericList *qmp_output_next_list(Visitor *v, GenericList *tail,
- size_t size)
-{
- return tail->next;
-}
-
-static void qmp_output_end_list(Visitor *v, void **obj)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QObject *value = qmp_output_pop(qov, obj);
- assert(qobject_type(value) == QTYPE_QLIST);
-}
-
-static void qmp_output_type_int64(Visitor *v, const char *name, int64_t *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qint_from_int(*obj));
-}
-
-static void qmp_output_type_uint64(Visitor *v, const char *name, uint64_t *obj,
- Error **errp)
-{
- /* FIXME: QMP outputs values larger than INT64_MAX as negative */
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qint_from_int(*obj));
-}
-
-static void qmp_output_type_bool(Visitor *v, const char *name, bool *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qbool_from_bool(*obj));
-}
-
-static void qmp_output_type_str(Visitor *v, const char *name, char **obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- if (*obj) {
- qmp_output_add(qov, name, qstring_from_str(*obj));
- } else {
- qmp_output_add(qov, name, qstring_from_str(""));
- }
-}
-
-static void qmp_output_type_number(Visitor *v, const char *name, double *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qfloat_from_double(*obj));
-}
-
-static void qmp_output_type_any(Visitor *v, const char *name, QObject **obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qobject_incref(*obj);
- qmp_output_add_obj(qov, name, *obj);
-}
-
-static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add_obj(qov, name, qnull());
-}
-
-/* Finish building, and return the root object.
- * The root object is never null. The caller becomes the object's
- * owner, and should use qobject_decref() when done with it. */
-static void qmp_output_complete(Visitor *v, void *opaque)
-{
- QmpOutputVisitor *qov = to_qov(v);
-
- /* A visit must have occurred, with each start paired with end. */
- assert(qov->root && QSLIST_EMPTY(&qov->stack));
- assert(opaque == qov->result);
-
- qobject_incref(qov->root);
- *qov->result = qov->root;
- qov->result = NULL;
-}
-
-static void qmp_output_free(Visitor *v)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QStackEntry *e;
-
- while (!QSLIST_EMPTY(&qov->stack)) {
- e = QSLIST_FIRST(&qov->stack);
- QSLIST_REMOVE_HEAD(&qov->stack, node);
- g_free(e);
- }
-
- qobject_decref(qov->root);
- g_free(qov);
-}
-
-Visitor *qmp_output_visitor_new(QObject **result)
-{
- QmpOutputVisitor *v;
-
- v = g_malloc0(sizeof(*v));
-
- v->visitor.type = VISITOR_OUTPUT;
- v->visitor.start_struct = qmp_output_start_struct;
- v->visitor.end_struct = qmp_output_end_struct;
- v->visitor.start_list = qmp_output_start_list;
- v->visitor.next_list = qmp_output_next_list;
- v->visitor.end_list = qmp_output_end_list;
- v->visitor.type_int64 = qmp_output_type_int64;
- v->visitor.type_uint64 = qmp_output_type_uint64;
- v->visitor.type_bool = qmp_output_type_bool;
- v->visitor.type_str = qmp_output_type_str;
- v->visitor.type_number = qmp_output_type_number;
- v->visitor.type_any = qmp_output_type_any;
- v->visitor.type_null = qmp_output_type_null;
- v->visitor.complete = qmp_output_complete;
- v->visitor.free = qmp_output_free;
-
- *result = NULL;
- v->result = result;
-
- return &v->visitor;
-}
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 68b24c98b0..e8053686f3 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -30,6 +30,14 @@ void qmp_register_command(const char *name, QmpCommandFunc *fn,
QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node);
}
+void qmp_unregister_command(const char *name)
+{
+ QmpCommand *cmd = qmp_find_command(name);
+
+ QTAILQ_REMOVE(&qmp_commands, cmd, node);
+ g_free(cmd);
+}
+
QmpCommand *qmp_find_command(const char *name)
{
QmpCommand *cmd;
diff --git a/qapi/qmp-input-visitor.c b/qapi/qobject-input-visitor.c
index 64dd392e6f..0063327b3b 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -14,7 +14,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "qapi/visitor-impl.h"
#include "qemu/queue.h"
#include "qemu-common.h"
@@ -34,7 +34,7 @@ typedef struct StackObject
QSLIST_ENTRY(StackObject) node;
} StackObject;
-struct QmpInputVisitor
+struct QObjectInputVisitor
{
Visitor visitor;
@@ -49,14 +49,14 @@ struct QmpInputVisitor
bool strict;
};
-static QmpInputVisitor *to_qiv(Visitor *v)
+static QObjectInputVisitor *to_qiv(Visitor *v)
{
- return container_of(v, QmpInputVisitor, visitor);
+ return container_of(v, QObjectInputVisitor, visitor);
}
-static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
- const char *name,
- bool consume)
+static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
+ const char *name,
+ bool consume, Error **errp)
{
StackObject *tos;
QObject *qobj;
@@ -64,6 +64,7 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
if (QSLIST_EMPTY(&qiv->stack)) {
/* Starting at root, name is ignored. */
+ assert(qiv->root);
return qiv->root;
}
@@ -79,10 +80,14 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
bool removed = g_hash_table_remove(tos->h, name);
assert(removed);
}
+ if (!ret) {
+ error_setg(errp, QERR_MISSING_PARAMETER, name);
+ }
} else {
assert(qobject_type(qobj) == QTYPE_QLIST);
assert(!name);
ret = qlist_entry_obj(tos->entry);
+ assert(ret);
if (consume) {
tos->entry = qlist_next(tos->entry);
}
@@ -97,8 +102,9 @@ static void qdict_add_key(const char *key, QObject *obj, void *opaque)
g_hash_table_insert(h, (gpointer) key, NULL);
}
-static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
- void *qapi, Error **errp)
+static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
+ QObject *obj, void *qapi,
+ Error **errp)
{
GHashTable *h;
StackObject *tos = g_new0(StackObject, 1);
@@ -120,9 +126,9 @@ static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
}
-static void qmp_input_check_struct(Visitor *v, Error **errp)
+static void qobject_input_check_struct(Visitor *v, Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
+ QObjectInputVisitor *qiv = to_qiv(v);
StackObject *tos = QSLIST_FIRST(&qiv->stack);
assert(tos && !tos->entry);
@@ -140,7 +146,7 @@ static void qmp_input_check_struct(Visitor *v, Error **errp)
}
}
-static void qmp_input_stack_object_free(StackObject *tos)
+static void qobject_input_stack_object_free(StackObject *tos)
{
if (tos->h) {
g_hash_table_unref(tos->h);
@@ -149,33 +155,36 @@ static void qmp_input_stack_object_free(StackObject *tos)
g_free(tos);
}
-static void qmp_input_pop(Visitor *v, void **obj)
+static void qobject_input_pop(Visitor *v, void **obj)
{
- QmpInputVisitor *qiv = to_qiv(v);
+ QObjectInputVisitor *qiv = to_qiv(v);
StackObject *tos = QSLIST_FIRST(&qiv->stack);
assert(tos && tos->qapi == obj);
QSLIST_REMOVE_HEAD(&qiv->stack, node);
- qmp_input_stack_object_free(tos);
+ qobject_input_stack_object_free(tos);
}
-static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
- size_t size, Error **errp)
+static void qobject_input_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
Error *err = NULL;
if (obj) {
*obj = NULL;
}
- if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
+ if (!qobj) {
+ return;
+ }
+ if (qobject_type(qobj) != QTYPE_QDICT) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"QDict");
return;
}
- qmp_input_push(qiv, qobj, obj, &err);
+ qobject_input_push(qiv, qobj, obj, &err);
if (err) {
error_propagate(errp, err);
return;
@@ -187,14 +196,18 @@ static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
}
-static void qmp_input_start_list(Visitor *v, const char *name,
- GenericList **list, size_t size, Error **errp)
+static void qobject_input_start_list(Visitor *v, const char *name,
+ GenericList **list, size_t size,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
const QListEntry *entry;
- if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
+ if (!qobj) {
+ return;
+ }
+ if (qobject_type(qobj) != QTYPE_QLIST) {
if (list) {
*list = NULL;
}
@@ -203,7 +216,7 @@ static void qmp_input_start_list(Visitor *v, const char *name,
return;
}
- entry = qmp_input_push(qiv, qobj, list, errp);
+ entry = qobject_input_push(qiv, qobj, list, errp);
if (list) {
if (entry) {
*list = g_malloc0(size);
@@ -213,10 +226,10 @@ static void qmp_input_start_list(Visitor *v, const char *name,
}
}
-static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
- size_t size)
+static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
+ size_t size)
{
- QmpInputVisitor *qiv = to_qiv(v);
+ QObjectInputVisitor *qiv = to_qiv(v);
StackObject *so = QSLIST_FIRST(&qiv->stack);
if (!so->entry) {
@@ -227,16 +240,15 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
}
-static void qmp_input_start_alternate(Visitor *v, const char *name,
- GenericAlternate **obj, size_t size,
- bool promote_int, Error **errp)
+static void qobject_input_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ bool promote_int, Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, false);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
if (!qobj) {
*obj = NULL;
- error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
return;
}
*obj = g_malloc0(size);
@@ -246,12 +258,17 @@ static void qmp_input_start_alternate(Visitor *v, const char *name,
}
}
-static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
- Error **errp)
+static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QInt *qint;
+ if (!qobj) {
+ return;
+ }
+ qint = qobject_to_qint(qobj);
if (!qint) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"integer");
@@ -261,13 +278,18 @@ static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
*obj = qint_get_int(qint);
}
-static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
- Error **errp)
+static void qobject_input_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
{
/* FIXME: qobject_to_qint mishandles values over INT64_MAX */
- QmpInputVisitor *qiv = to_qiv(v);
- QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QInt *qint;
+ if (!qobj) {
+ return;
+ }
+ qint = qobject_to_qint(qobj);
if (!qint) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"integer");
@@ -277,12 +299,17 @@ static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
*obj = qint_get_int(qint);
}
-static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
- Error **errp)
+static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true));
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QBool *qbool;
+ if (!qobj) {
+ return;
+ }
+ qbool = qobject_to_qbool(qobj);
if (!qbool) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"boolean");
@@ -292,14 +319,19 @@ static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
*obj = qbool_get_bool(qbool);
}
-static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
- Error **errp)
+static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QString *qstr;
+ *obj = NULL;
+ if (!qobj) {
+ return;
+ }
+ qstr = qobject_to_qstring(qobj);
if (!qstr) {
- *obj = NULL;
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"string");
return;
@@ -308,14 +340,17 @@ static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
*obj = g_strdup(qstring_get_str(qstr));
}
-static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
- Error **errp)
+static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
QInt *qint;
QFloat *qfloat;
+ if (!qobj) {
+ return;
+ }
qint = qobject_to_qint(qobj);
if (qint) {
*obj = qint_get_int(qobject_to_qint(qobj));
@@ -332,20 +367,29 @@ static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
"number");
}
-static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,
- Error **errp)
+static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
+ Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ *obj = NULL;
+ if (!qobj) {
+ return;
+ }
qobject_incref(qobj);
*obj = qobj;
}
-static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
+static void qobject_input_type_null(Visitor *v, const char *name, Error **errp)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ if (!qobj) {
+ return;
+ }
if (qobject_type(qobj) != QTYPE_QNULL) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -353,10 +397,10 @@ static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
}
}
-static void qmp_input_optional(Visitor *v, const char *name, bool *present)
+static void qobject_input_optional(Visitor *v, const char *name, bool *present)
{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, false);
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, false, NULL);
if (!qobj) {
*present = false;
@@ -366,43 +410,44 @@ static void qmp_input_optional(Visitor *v, const char *name, bool *present)
*present = true;
}
-static void qmp_input_free(Visitor *v)
+static void qobject_input_free(Visitor *v)
{
- QmpInputVisitor *qiv = to_qiv(v);
+ QObjectInputVisitor *qiv = to_qiv(v);
while (!QSLIST_EMPTY(&qiv->stack)) {
StackObject *tos = QSLIST_FIRST(&qiv->stack);
QSLIST_REMOVE_HEAD(&qiv->stack, node);
- qmp_input_stack_object_free(tos);
+ qobject_input_stack_object_free(tos);
}
qobject_decref(qiv->root);
g_free(qiv);
}
-Visitor *qmp_input_visitor_new(QObject *obj, bool strict)
+Visitor *qobject_input_visitor_new(QObject *obj, bool strict)
{
- QmpInputVisitor *v;
+ QObjectInputVisitor *v;
+ assert(obj);
v = g_malloc0(sizeof(*v));
v->visitor.type = VISITOR_INPUT;
- v->visitor.start_struct = qmp_input_start_struct;
- v->visitor.check_struct = qmp_input_check_struct;
- v->visitor.end_struct = qmp_input_pop;
- v->visitor.start_list = qmp_input_start_list;
- v->visitor.next_list = qmp_input_next_list;
- v->visitor.end_list = qmp_input_pop;
- v->visitor.start_alternate = qmp_input_start_alternate;
- v->visitor.type_int64 = qmp_input_type_int64;
- v->visitor.type_uint64 = qmp_input_type_uint64;
- v->visitor.type_bool = qmp_input_type_bool;
- v->visitor.type_str = qmp_input_type_str;
- v->visitor.type_number = qmp_input_type_number;
- v->visitor.type_any = qmp_input_type_any;
- v->visitor.type_null = qmp_input_type_null;
- v->visitor.optional = qmp_input_optional;
- v->visitor.free = qmp_input_free;
+ v->visitor.start_struct = qobject_input_start_struct;
+ v->visitor.check_struct = qobject_input_check_struct;
+ v->visitor.end_struct = qobject_input_pop;
+ v->visitor.start_list = qobject_input_start_list;
+ v->visitor.next_list = qobject_input_next_list;
+ v->visitor.end_list = qobject_input_pop;
+ v->visitor.start_alternate = qobject_input_start_alternate;
+ v->visitor.type_int64 = qobject_input_type_int64;
+ v->visitor.type_uint64 = qobject_input_type_uint64;
+ v->visitor.type_bool = qobject_input_type_bool;
+ v->visitor.type_str = qobject_input_type_str;
+ v->visitor.type_number = qobject_input_type_number;
+ v->visitor.type_any = qobject_input_type_any;
+ v->visitor.type_null = qobject_input_type_null;
+ v->visitor.optional = qobject_input_optional;
+ v->visitor.free = qobject_input_free;
v->strict = strict;
v->root = obj;
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
new file mode 100644
index 0000000000..871127079d
--- /dev/null
+++ b/qapi/qobject-output-visitor.c
@@ -0,0 +1,254 @@
+/*
+ * Core Definitions for QAPI/QMP Command Registry
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/qobject-output-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qemu-common.h"
+#include "qapi/qmp/types.h"
+
+typedef struct QStackEntry {
+ QObject *value;
+ void *qapi; /* sanity check that caller uses same pointer */
+ QSLIST_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+struct QObjectOutputVisitor {
+ Visitor visitor;
+ QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
+ QObject *root; /* Root of the output visit */
+ QObject **result; /* User's storage location for result */
+};
+
+#define qobject_output_add(qov, name, value) \
+ qobject_output_add_obj(qov, name, QOBJECT(value))
+#define qobject_output_push(qov, value, qapi) \
+ qobject_output_push_obj(qov, QOBJECT(value), qapi)
+
+static QObjectOutputVisitor *to_qov(Visitor *v)
+{
+ return container_of(v, QObjectOutputVisitor, visitor);
+}
+
+/* Push @value onto the stack of current QObjects being built */
+static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
+ void *qapi)
+{
+ QStackEntry *e = g_malloc0(sizeof(*e));
+
+ assert(qov->root);
+ assert(value);
+ e->value = value;
+ e->qapi = qapi;
+ QSLIST_INSERT_HEAD(&qov->stack, e, node);
+}
+
+/* Pop a value off the stack of QObjects being built, and return it. */
+static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *value;
+
+ assert(e);
+ assert(e->qapi == qapi);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ value = e->value;
+ assert(value);
+ g_free(e);
+ return value;
+}
+
+/* Add @value to the current QObject being built.
+ * If the stack is visiting a dictionary or list, @value is now owned
+ * by that container. Otherwise, @value is now the root. */
+static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
+ QObject *value)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *cur = e ? e->value : NULL;
+
+ if (!cur) {
+ /* Don't allow reuse of visitor on more than one root */
+ assert(!qov->root);
+ qov->root = value;
+ } else {
+ switch (qobject_type(cur)) {
+ case QTYPE_QDICT:
+ assert(name);
+ qdict_put_obj(qobject_to_qdict(cur), name, value);
+ break;
+ case QTYPE_QLIST:
+ assert(!name);
+ qlist_append_obj(qobject_to_qlist(cur), value);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
+static void qobject_output_start_struct(Visitor *v, const char *name,
+ void **obj, size_t unused, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QDict *dict = qdict_new();
+
+ qobject_output_add(qov, name, dict);
+ qobject_output_push(qov, dict, obj);
+}
+
+static void qobject_output_end_struct(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QDICT);
+}
+
+static void qobject_output_start_list(Visitor *v, const char *name,
+ GenericList **listp, size_t size,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QList *list = qlist_new();
+
+ qobject_output_add(qov, name, list);
+ qobject_output_push(qov, list, listp);
+}
+
+static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ return tail->next;
+}
+
+static void qobject_output_end_list(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QLIST);
+}
+
+static void qobject_output_type_int64(Visitor *v, const char *name,
+ int64_t *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qobject_output_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ /* FIXME values larger than INT64_MAX become negative */
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qbool_from_bool(*obj));
+}
+
+static void qobject_output_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ if (*obj) {
+ qobject_output_add(qov, name, qstring_from_str(*obj));
+ } else {
+ qobject_output_add(qov, name, qstring_from_str(""));
+ }
+}
+
+static void qobject_output_type_number(Visitor *v, const char *name,
+ double *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qfloat_from_double(*obj));
+}
+
+static void qobject_output_type_any(Visitor *v, const char *name,
+ QObject **obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_incref(*obj);
+ qobject_output_add_obj(qov, name, *obj);
+}
+
+static void qobject_output_type_null(Visitor *v, const char *name, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add_obj(qov, name, qnull());
+}
+
+/* Finish building, and return the root object.
+ * The root object is never null. The caller becomes the object's
+ * owner, and should use qobject_decref() when done with it. */
+static void qobject_output_complete(Visitor *v, void *opaque)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+
+ /* A visit must have occurred, with each start paired with end. */
+ assert(qov->root && QSLIST_EMPTY(&qov->stack));
+ assert(opaque == qov->result);
+
+ qobject_incref(qov->root);
+ *qov->result = qov->root;
+ qov->result = NULL;
+}
+
+static void qobject_output_free(Visitor *v)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QStackEntry *e;
+
+ while (!QSLIST_EMPTY(&qov->stack)) {
+ e = QSLIST_FIRST(&qov->stack);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ g_free(e);
+ }
+
+ qobject_decref(qov->root);
+ g_free(qov);
+}
+
+Visitor *qobject_output_visitor_new(QObject **result)
+{
+ QObjectOutputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_OUTPUT;
+ v->visitor.start_struct = qobject_output_start_struct;
+ v->visitor.end_struct = qobject_output_end_struct;
+ v->visitor.start_list = qobject_output_start_list;
+ v->visitor.next_list = qobject_output_next_list;
+ v->visitor.end_list = qobject_output_end_list;
+ v->visitor.type_int64 = qobject_output_type_int64;
+ v->visitor.type_uint64 = qobject_output_type_uint64;
+ v->visitor.type_bool = qobject_output_type_bool;
+ v->visitor.type_str = qobject_output_type_str;
+ v->visitor.type_number = qobject_output_type_number;
+ v->visitor.type_any = qobject_output_type_any;
+ v->visitor.type_null = qobject_output_type_null;
+ v->visitor.complete = qobject_output_complete;
+ v->visitor.free = qobject_output_free;
+
+ *result = NULL;
+ v->result = result;
+
+ return &v->visitor;
+}
diff --git a/qapi/rocker.json b/qapi/rocker.json
index 2fe7fdfa66..ace27760f1 100644
--- a/qapi/rocker.json
+++ b/qapi/rocker.json
@@ -1,5 +1,5 @@
##
-# @Rocker:
+# @RockerSwitch:
#
# Rocker switch information.
#
diff --git a/qapi/trace-events b/qapi/trace-events
new file mode 100644
index 0000000000..2c5d3bc7d7
--- /dev/null
+++ b/qapi/trace-events
@@ -0,0 +1,33 @@
+# qapi-visit-core.c
+visit_free(void *v) "v=%p"
+visit_complete(void *v, void *opaque) "v=%p opaque=%p"
+
+visit_start_struct(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_check_struct(void *v) "v=%p"
+visit_end_struct(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_list(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu"
+visit_end_list(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_alternate(void *v, const char *name, void *obj, size_t size, bool promote_int) "v=%p name=%s obj=%p size=%zu promote_int=%d"
+visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
+
+visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
+
+visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p"
+visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint8(void *v, const char *name, uint8_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint16(void *v, const char *name, uint16_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint32(void *v, const char *name, uint32_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint64(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_int8(void *v, const char *name, int8_t *obj) "v=%p name=%s obj=%p"
+visit_type_int16(void *v, const char *name, int16_t *obj) "v=%p name=%s obj=%p"
+visit_type_int32(void *v, const char *name, int32_t *obj) "v=%p name=%s obj=%p"
+visit_type_int64(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_size(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_bool(void *v, const char *name, bool *obj) "v=%p name=%s obj=%p"
+visit_type_str(void *v, const char *name, char **obj) "v=%p name=%s obj=%p"
+visit_type_number(void *v, const char *name, double *obj) "v=%p name=%s obj=%p"
+visit_type_any(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
+visit_type_null(void *v, const char *name) "v=%p name=%s"
diff --git a/qapi/trace.json b/qapi/trace.json
index e87214677c..4fd39b7792 100644
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -17,7 +17,7 @@
#
# @enabled: The event is dynamically enabled.
#
-# Since 2.2
+# Since: 2.2
##
{ 'enum': 'TraceEventState',
'data': ['unavailable', 'disabled', 'enabled'] }
@@ -34,7 +34,7 @@
# An event is per-vCPU if it has the "vcpu" property in the "trace-events"
# files.
#
-# Since 2.2
+# Since: 2.2
##
{ 'struct': 'TraceEventInfo',
'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} }
@@ -58,7 +58,7 @@
# exact match, @vcpu is given and the event does not have the "vcpu" property,
# an error is returned.
#
-# Since 2.2
+# Since: 2.2
##
{ 'command': 'trace-event-get-state',
'data': {'name': 'str', '*vcpu': 'int'},
@@ -83,7 +83,7 @@
# match, @vcpu is given and the event does not have the "vcpu" property, an
# error is returned.
#
-# Since 2.2
+# Since: 2.2
##
{ 'command': 'trace-event-set-state',
'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool',