summaryrefslogtreecommitdiffstats
path: root/qemu/qapi
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:18:31 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:42:15 +0300
commit437fd90c0250dee670290f9b714253671a990160 (patch)
treeb871786c360704244a07411c69fb58da9ead4a06 /qemu/qapi
parent5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 (diff)
These changes are the raw update to qemu-2.6.
Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'qemu/qapi')
-rw-r--r--qemu/qapi/block-core.json605
-rw-r--r--qemu/qapi/block.json38
-rw-r--r--qemu/qapi/common.json21
-rw-r--r--qemu/qapi/crypto.json222
-rw-r--r--qemu/qapi/event.json33
-rw-r--r--qemu/qapi/introspect.json279
-rw-r--r--qemu/qapi/opts-visitor.c74
-rw-r--r--qemu/qapi/qapi-dealloc-visitor.c82
-rw-r--r--qemu/qapi/qapi-util.c3
-rw-r--r--qemu/qapi/qapi-visit-core.c278
-rw-r--r--qemu/qapi/qmp-dispatch.c5
-rw-r--r--qemu/qapi/qmp-event.c10
-rw-r--r--qemu/qapi/qmp-input-visitor.c134
-rw-r--r--qemu/qapi/qmp-output-visitor.c123
-rw-r--r--qemu/qapi/qmp-registry.c2
-rw-r--r--qemu/qapi/string-input-visitor.c69
-rw-r--r--qemu/qapi/string-output-visitor.c55
17 files changed, 1526 insertions, 507 deletions
diff --git a/qemu/qapi/block-core.json b/qemu/qapi/block-core.json
index 7b2efb867..1d09079cc 100644
--- a/qemu/qapi/block-core.json
+++ b/qemu/qapi/block-core.json
@@ -186,6 +186,33 @@
'*fragmented-clusters': 'int', '*compressed-clusters': 'int' } }
##
+# @MapEntry:
+#
+# Mapping information from a virtual block range to a host file range
+#
+# @start: the start byte of the mapped virtual range
+#
+# @length: the number of bytes of the mapped virtual range
+#
+# @data: whether the mapped range has data
+#
+# @zero: whether the virtual blocks are zeroed
+#
+# @depth: the depth of the mapping
+#
+# @offset: #optional the offset in file that the virtual sectors are mapped to
+#
+# @filename: #optional filename that is referred to by @offset
+#
+# Since: 2.6
+#
+##
+{ 'struct': 'MapEntry',
+ 'data': {'start': 'int', 'length': 'int', 'data': 'bool',
+ 'zero': 'bool', 'depth': 'int', '*offset': 'int',
+ '*filename': 'str' } }
+
+##
# @BlockdevCacheInfo
#
# Cache mode information for a block device
@@ -215,10 +242,12 @@
# @drv: the name of the block format used to open the backing device. As of
# 0.14.0 this can be: 'blkdebug', 'bochs', 'cloop', 'cow', 'dmg',
# 'file', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
-# 'host_floppy', 'http', 'https', 'nbd', 'parallels', 'qcow',
+# 'http', 'https', 'luks', 'nbd', 'parallels', 'qcow',
# 'qcow2', 'raw', 'tftp', 'vdi', 'vmdk', 'vpc', 'vvfat'
# 2.2: 'archipelago' added, 'cow' dropped
# 2.3: 'host_floppy' deprecated
+# 2.5: 'host_floppy' dropped
+# 2.6: 'luks' added
#
# @backing_file: #optional the name of the backing file (for copy-on-write)
#
@@ -245,17 +274,41 @@
#
# @image: the info of image used (since: 1.6)
#
-# @bps_max: #optional total max in bytes (Since 1.7)
+# @bps_max: #optional total throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_rd_max: #optional read throughput limit during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_wr_max: #optional write throughput limit during bursts,
+# in bytes (Since 1.7)
#
-# @bps_rd_max: #optional read max in bytes (Since 1.7)
+# @iops_max: #optional total I/O operations per second during bursts,
+# in bytes (Since 1.7)
#
-# @bps_wr_max: #optional write max in bytes (Since 1.7)
+# @iops_rd_max: #optional read I/O operations per second during bursts,
+# in bytes (Since 1.7)
#
-# @iops_max: #optional total I/O operations max (Since 1.7)
+# @iops_wr_max: #optional write I/O operations per second during bursts,
+# in bytes (Since 1.7)
#
-# @iops_rd_max: #optional read I/O operations max (Since 1.7)
+# @bps_max_length: #optional maximum length of the @bps_max burst
+# period, in seconds. (Since 2.6)
#
-# @iops_wr_max: #optional write I/O operations max (Since 1.7)
+# @bps_rd_max_length: #optional maximum length of the @bps_rd_max
+# burst period, in seconds. (Since 2.6)
+#
+# @bps_wr_max_length: #optional maximum length of the @bps_wr_max
+# burst period, in seconds. (Since 2.6)
+#
+# @iops_max_length: #optional maximum length of the @iops burst
+# period, in seconds. (Since 2.6)
+#
+# @iops_rd_max_length: #optional maximum length of the @iops_rd_max
+# burst period, in seconds. (Since 2.6)
+#
+# @iops_wr_max_length: #optional maximum length of the @iops_wr_max
+# burst period, in seconds. (Since 2.6)
#
# @iops_size: #optional an I/O size in bytes (Since 1.7)
#
@@ -280,6 +333,9 @@
'*bps_max': 'int', '*bps_rd_max': 'int',
'*bps_wr_max': 'int', '*iops_max': 'int',
'*iops_rd_max': 'int', '*iops_wr_max': 'int',
+ '*bps_max_length': 'int', '*bps_rd_max_length': 'int',
+ '*bps_wr_max_length': 'int', '*iops_max_length': 'int',
+ '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int',
'*iops_size': 'int', '*group': 'str', 'cache': 'BlockdevCacheInfo',
'write_threshold': 'int' } }
@@ -381,8 +437,8 @@
# @locked: True if the guest has locked this device from having its media
# removed
#
-# @tray_open: #optional True if the device has a tray and it is open
-# (only present if removable is true)
+# @tray_open: #optional True if the device's tray is open
+# (only present if it has a tray)
#
# @dirty-bitmaps: #optional dirty bitmaps information (only present if the
# driver has one or more dirty bitmaps) (Since 2.0)
@@ -413,6 +469,59 @@
##
{ 'command': 'query-block', 'returns': ['BlockInfo'] }
+
+##
+# @BlockDeviceTimedStats:
+#
+# Statistics of a block device during a given interval of time.
+#
+# @interval_length: Interval used for calculating the statistics,
+# in seconds.
+#
+# @min_rd_latency_ns: Minimum latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @min_wr_latency_ns: Minimum latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @min_flush_latency_ns: Minimum latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @max_rd_latency_ns: Maximum latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @max_wr_latency_ns: Maximum latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @max_flush_latency_ns: Maximum latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_rd_latency_ns: Average latency of read operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_wr_latency_ns: Average latency of write operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_flush_latency_ns: Average latency of flush operations in the
+# defined interval, in nanoseconds.
+#
+# @avg_rd_queue_depth: Average number of pending read operations
+# in the defined interval.
+#
+# @avg_wr_queue_depth: Average number of pending write operations
+# in the defined interval.
+#
+# Since: 2.5
+##
+
+{ 'struct': 'BlockDeviceTimedStats',
+ 'data': { 'interval_length': 'int', 'min_rd_latency_ns': 'int',
+ 'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int',
+ 'min_wr_latency_ns': 'int', 'max_wr_latency_ns': 'int',
+ 'avg_wr_latency_ns': 'int', 'min_flush_latency_ns': 'int',
+ 'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int',
+ 'avg_rd_queue_depth': 'number', 'avg_wr_queue_depth': 'number' } }
+
##
# @BlockDeviceStats:
#
@@ -447,6 +556,37 @@
# @wr_merged: Number of write requests that have been merged into another
# request (Since 2.3).
#
+# @idle_time_ns: #optional Time since the last I/O operation, in
+# nanoseconds. If the field is absent it means that
+# there haven't been any operations yet (Since 2.5).
+#
+# @failed_rd_operations: The number of failed read operations
+# performed by the device (Since 2.5)
+#
+# @failed_wr_operations: The number of failed write operations
+# performed by the device (Since 2.5)
+#
+# @failed_flush_operations: The number of failed flush operations
+# performed by the device (Since 2.5)
+#
+# @invalid_rd_operations: The number of invalid read operations
+# performed by the device (Since 2.5)
+#
+# @invalid_wr_operations: The number of invalid write operations
+# performed by the device (Since 2.5)
+#
+# @invalid_flush_operations: The number of invalid flush operations
+# performed by the device (Since 2.5)
+#
+# @account_invalid: Whether invalid operations are included in the
+# last access statistics (Since 2.5)
+#
+# @account_failed: Whether failed operations are included in the
+# latency and last access statistics (Since 2.5)
+#
+# @timed_stats: Statistics specific to the set of previously defined
+# intervals of time (Since 2.5)
+#
# Since: 0.14.0
##
{ 'struct': 'BlockDeviceStats',
@@ -454,7 +594,12 @@
'wr_operations': 'int', 'flush_operations': 'int',
'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int',
'rd_total_time_ns': 'int', 'wr_highest_offset': 'int',
- 'rd_merged': 'int', 'wr_merged': 'int' } }
+ 'rd_merged': 'int', 'wr_merged': 'int', '*idle_time_ns': 'int',
+ 'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
+ 'failed_flush_operations': 'int', 'invalid_rd_operations': 'int',
+ 'invalid_wr_operations': 'int', 'invalid_flush_operations': 'int',
+ 'account_invalid': 'bool', 'account_failed': 'bool',
+ 'timed_stats': ['BlockDeviceTimedStats'] } }
##
# @BlockStats:
@@ -681,7 +826,7 @@
'data': [ 'existing', 'absolute-paths' ] }
##
-# @BlockdevSnapshot
+# @BlockdevSnapshotSync
#
# Either @device or @node-name must be set but not both.
#
@@ -698,12 +843,27 @@
# @mode: #optional whether and how QEMU should create a new image, default is
# 'absolute-paths'.
##
-{ 'struct': 'BlockdevSnapshot',
+{ 'struct': 'BlockdevSnapshotSync',
'data': { '*device': 'str', '*node-name': 'str',
'snapshot-file': 'str', '*snapshot-node-name': 'str',
'*format': 'str', '*mode': 'NewImageMode' } }
##
+# @BlockdevSnapshot
+#
+# @node: device or node name that will have a snapshot created.
+#
+# @overlay: reference to the existing block device that will become
+# the overlay of @node, as part of creating the snapshot.
+# It must not have a current backing file (this can be
+# achieved by passing "backing": "" to blockdev-add).
+#
+# Since 2.5
+##
+{ 'struct': 'BlockdevSnapshot',
+ 'data': { 'node': 'str', 'overlay': 'str' } }
+
+##
# @DriveBackup
#
# @device: the name of the device which should be copied.
@@ -789,7 +949,7 @@
#
# Generates a synchronous snapshot of a block device.
#
-# For the arguments, see the documentation of BlockdevSnapshot.
+# For the arguments, see the documentation of BlockdevSnapshotSync.
#
# Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound
@@ -797,6 +957,19 @@
# Since 0.14.0
##
{ 'command': 'blockdev-snapshot-sync',
+ 'data': 'BlockdevSnapshotSync' }
+
+
+##
+# @blockdev-snapshot
+#
+# Generates a snapshot of a block device.
+#
+# For the arguments, see the documentation of BlockdevSnapshot.
+#
+# Since 2.5
+##
+{ 'command': 'blockdev-snapshot',
'data': 'BlockdevSnapshot' }
##
@@ -1066,6 +1239,54 @@
'data': 'BlockDirtyBitmap' }
##
+# @blockdev-mirror
+#
+# Start mirroring a block device's writes to a new destination.
+#
+# @device: the name of the device 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.
+#
+# @replaces: #optional with sync=full graph node name to be replaced by the new
+# image when a whole image copy is done. This can be used to repair
+# broken Quorum files.
+#
+# @speed: #optional the maximum speed, in bytes per second
+#
+# @sync: what parts of the disk image should be copied to the destination
+# (all the disk, only the sectors allocated in the topmost image, or
+# only new I/O).
+#
+# @granularity: #optional granularity of the dirty bitmap, default is 64K
+# if the image format doesn't have clusters, 4K if the clusters
+# are smaller than that, else the cluster size. Must be a
+# power of 2 between 512 and 64M
+#
+# @buf-size: #optional maximum amount of data in flight from source to
+# target
+#
+# @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).
+#
+# @on-target-error: #optional the action to take on an error on the target,
+# default 'report' (no limitations, since this applies to
+# a different block device than @device).
+#
+# Returns: nothing on success.
+#
+# Since 2.6
+##
+{ 'command': 'blockdev-mirror',
+ 'data': { 'device': 'str', 'target': 'str',
+ '*replaces': 'str',
+ 'sync': 'MirrorSyncMode',
+ '*speed': 'int', '*granularity': 'uint32',
+ '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
+ '*on-target-error': 'BlockdevOnError' } }
+
+##
# @block_set_io_throttle:
#
# Change I/O throttle limits for a block drive.
@@ -1101,21 +1322,57 @@
#
# @iops: total I/O operations per second
#
-# @ops_rd: read I/O operations per second
+# @iops_rd: read I/O operations per second
#
# @iops_wr: write I/O operations per second
#
-# @bps_max: #optional total max in bytes (Since 1.7)
+# @bps_max: #optional total throughput limit during bursts,
+# in bytes (Since 1.7)
#
-# @bps_rd_max: #optional read max in bytes (Since 1.7)
+# @bps_rd_max: #optional read throughput limit during bursts,
+# in bytes (Since 1.7)
#
-# @bps_wr_max: #optional write max in bytes (Since 1.7)
+# @bps_wr_max: #optional write throughput limit during bursts,
+# in bytes (Since 1.7)
#
-# @iops_max: #optional total I/O operations max (Since 1.7)
+# @iops_max: #optional total I/O operations per second during bursts,
+# in bytes (Since 1.7)
#
-# @iops_rd_max: #optional read I/O operations max (Since 1.7)
+# @iops_rd_max: #optional read I/O operations per second during bursts,
+# in bytes (Since 1.7)
#
-# @iops_wr_max: #optional write I/O operations max (Since 1.7)
+# @iops_wr_max: #optional write I/O operations per second during bursts,
+# in bytes (Since 1.7)
+#
+# @bps_max_length: #optional maximum length of the @bps_max burst
+# period, in seconds. It must only
+# be set if @bps_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @bps_rd_max_length: #optional maximum length of the @bps_rd_max
+# burst period, in seconds. It must only
+# be set if @bps_rd_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @bps_wr_max_length: #optional maximum length of the @bps_wr_max
+# burst period, in seconds. It must only
+# be set if @bps_wr_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_max_length: #optional maximum length of the @iops burst
+# period, in seconds. It must only
+# be set if @iops_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_rd_max_length: #optional maximum length of the @iops_rd_max
+# burst period, in seconds. It must only
+# be set if @iops_rd_max is set as well.
+# Defaults to 1. (Since 2.6)
+#
+# @iops_wr_max_length: #optional maximum length of the @iops_wr_max
+# burst period, in seconds. It must only
+# be set if @iops_wr_max is set as well.
+# Defaults to 1. (Since 2.6)
#
# @iops_size: #optional an I/O size in bytes (Since 1.7)
#
@@ -1132,6 +1389,9 @@
'*bps_max': 'int', '*bps_rd_max': 'int',
'*bps_wr_max': 'int', '*iops_max': 'int',
'*iops_rd_max': 'int', '*iops_wr_max': 'int',
+ '*bps_max_length': 'int', '*bps_rd_max_length': 'int',
+ '*bps_wr_max_length': 'int', '*iops_max_length': 'int',
+ '*iops_rd_max_length': 'int', '*iops_wr_max_length': 'int',
'*iops_size': 'int', '*group': 'str' } }
##
@@ -1355,7 +1615,6 @@
#
# Includes cache-related options for block devices
#
-# @writeback: #optional enables writeback mode for any caches (default: true)
# @direct: #optional enables use of O_DIRECT (bypass the host page cache;
# default: false)
# @no-flush: #optional ignore any flush requests for the device (default:
@@ -1364,8 +1623,7 @@
# Since: 1.7
##
{ 'struct': 'BlockdevCacheOptions',
- 'data': { '*writeback': 'bool',
- '*direct': 'bool',
+ 'data': { '*direct': 'bool',
'*no-flush': 'bool' } }
##
@@ -1373,56 +1631,18 @@
#
# Drivers that are supported in block device operations.
#
-# @host_device, @host_cdrom, @host_floppy: Since 2.1
-# @host_floppy: deprecated since 2.3
+# @host_device, @host_cdrom: Since 2.1
#
# Since: 2.0
##
{ 'enum': 'BlockdevDriver',
'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
- 'host_floppy', 'http', 'https', 'null-aio', 'null-co', 'parallels',
+ 'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
'vmdk', 'vpc', 'vvfat' ] }
##
-# @BlockdevOptionsBase
-#
-# Options that 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 is a required option on the top level of blockdev-add, and
-# currently not allowed on any other level.
-# @node-name: #optional the name of a block driver state node (Since 2.0)
-# @discard: #optional discard-related options (default: ignore)
-# @cache: #optional cache-related options
-# @aio: #optional AIO backend (default: threads)
-# @rerror: #optional how to handle read errors on the device
-# (default: report)
-# @werror: #optional how to handle write errors on the device
-# (default: enospc)
-# @read-only: #optional whether the block device should be read-only
-# (default: false)
-# @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
-# (default: off)
-#
-# Since: 1.7
-##
-{ 'struct': 'BlockdevOptionsBase',
- 'data': { 'driver': 'BlockdevDriver',
- '*id': 'str',
- '*node-name': 'str',
- '*discard': 'BlockdevDiscardOptions',
- '*cache': 'BlockdevCacheOptions',
- '*aio': 'BlockdevAioOptions',
- '*rerror': 'BlockdevOnError',
- '*werror': 'BlockdevOnError',
- '*read-only': 'bool',
- '*detect-zeroes': 'BlockdevDetectZeroesOptions' } }
-
-##
# @BlockdevOptionsFile
#
# Driver specific block device options for the file backend and similar
@@ -1485,6 +1705,22 @@
'data': { 'file': 'BlockdevRef' } }
##
+# @BlockdevOptionsLUKS
+#
+# Driver specific block device options for LUKS.
+#
+# @key-secret: #optional the ID of a QCryptoSecret object providing
+# the decryption key (since 2.6). Mandatory except when
+# doing a metadata-only probe of the image.
+#
+# Since: 2.6
+##
+{ 'struct': 'BlockdevOptionsLUKS',
+ 'base': 'BlockdevOptionsGenericFormat',
+ 'data': { '*key-secret': 'str' } }
+
+
+##
# @BlockdevOptionsGenericCOWFormat
#
# Driver specific block device options for image format that have no option
@@ -1592,6 +1828,10 @@
# @refcount-cache-size: #optional the maximum size of the refcount block cache
# in bytes (since 2.2)
#
+# @cache-clean-interval: #optional clean unused entries in the L2 and refcount
+# caches. The interval is in seconds. The default value
+# is 0 and it disables this feature (since 2.5)
+#
# Since: 1.7
##
{ 'struct': 'BlockdevOptionsQcow2',
@@ -1603,7 +1843,8 @@
'*overlap-check': 'Qcow2OverlapChecks',
'*cache-size': 'int',
'*l2-cache-size': 'int',
- '*refcount-cache-size': 'int' } }
+ '*refcount-cache-size': 'int',
+ '*cache-clean-interval': 'int' } }
##
@@ -1640,21 +1881,23 @@
# @BlkdebugEvent
#
# Trigger events supported by blkdebug.
+#
+# Since: 2.0
##
-{ 'enum': 'BlkdebugEvent',
- 'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
- 'l1_grow.activate_table', 'l2_load', 'l2_update',
- 'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
+{ 'enum': 'BlkdebugEvent', 'prefix': 'BLKDBG',
+ 'data': [ 'l1_update', 'l1_grow_alloc_table', 'l1_grow_write_table',
+ 'l1_grow_activate_table', 'l2_load', 'l2_update',
+ 'l2_update_compressed', 'l2_alloc_cow_read', 'l2_alloc_write',
'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
'refblock_load', 'refblock_update', 'refblock_update_part',
- 'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
- 'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
- 'refblock_alloc.switch_table', 'cluster_alloc',
+ 'refblock_alloc', 'refblock_alloc_hookup', 'refblock_alloc_write',
+ 'refblock_alloc_write_blocks', 'refblock_alloc_write_table',
+ 'refblock_alloc_switch_table', 'cluster_alloc',
'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
- 'flush_to_disk', 'pwritev_rmw.head', 'pwritev_rmw.after_head',
- 'pwritev_rmw.tail', 'pwritev_rmw.after_tail', 'pwritev',
+ 'flush_to_disk', 'pwritev_rmw_head', 'pwritev_rmw_after_head',
+ 'pwritev_rmw_tail', 'pwritev_rmw_after_tail', 'pwritev',
'pwritev_zero', 'pwritev_done', 'empty_image_prepare' ] }
##
@@ -1791,12 +2034,55 @@
##
# @BlockdevOptions
#
-# Options for creating a block device.
+# 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.
+# @discard: #optional discard-related options (default: ignore)
+# @cache: #optional cache-related options
+# @aio: #optional AIO backend (default: threads)
+# @rerror: #optional how to handle read errors on the device
+# (default: report)
+# @werror: #optional how to handle write errors on the device
+# (default: enospc)
+# @read-only: #optional whether the block device should be read-only
+# (default: false)
+# @stats-account-invalid: #optional whether to include invalid
+# operations when computing last access statistics
+# (default: true) (Since 2.5)
+# @stats-account-failed: #optional whether to include failed
+# operations when computing latency and last
+# access statistics (default: true) (Since 2.5)
+# @stats-intervals: #optional list of intervals for collecting I/O
+# statistics, in seconds (default: none) (Since 2.5)
+# @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
+# (default: off)
+#
+# Remaining options are determined by the block driver.
#
# Since: 1.7
##
{ 'union': 'BlockdevOptions',
- 'base': 'BlockdevOptionsBase',
+ 'base': { 'driver': 'BlockdevDriver',
+ '*id': 'str',
+ '*node-name': 'str',
+ '*discard': 'BlockdevDiscardOptions',
+ '*cache': 'BlockdevCacheOptions',
+ '*aio': 'BlockdevAioOptions',
+ '*rerror': 'BlockdevOnError',
+ '*werror': 'BlockdevOnError',
+ '*read-only': 'bool',
+ '*stats-account-invalid': 'bool',
+ '*stats-account-failed': 'bool',
+ '*stats-intervals': ['int'],
+ '*detect-zeroes': 'BlockdevDetectZeroesOptions' },
'discriminator': 'driver',
'data': {
'archipelago':'BlockdevOptionsArchipelago',
@@ -1811,10 +2097,10 @@
# TODO gluster: Wait for structured options
'host_cdrom': 'BlockdevOptionsFile',
'host_device':'BlockdevOptionsFile',
- 'host_floppy':'BlockdevOptionsFile',
'http': 'BlockdevOptionsFile',
'https': 'BlockdevOptionsFile',
# TODO iscsi: Wait for structured options
+ 'luks': 'BlockdevOptionsLUKS',
# TODO nbd: Should take InetSocketAddress for 'host'?
# TODO nfs: Wait for structured options
'null-aio': 'BlockdevOptionsNull',
@@ -1855,11 +2141,13 @@
##
# @blockdev-add:
#
-# Creates a new block device.
+# Creates a new block device. If the @id option is given at the top level, a
+# BlockBackend will be created; otherwise, @node-name is mandatory at the top
+# level and no BlockBackend will be created.
#
# This command is still a work in progress. It doesn't support all
-# block drivers, it lacks a matching blockdev-del, and more. Stay
-# away from it unless you want to help with its development.
+# 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
#
@@ -1867,6 +2155,165 @@
##
{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
+##
+# @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.
+#
+# 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.
+#
+# Since: 2.5
+##
+{ 'command': 'x-blockdev-del', 'data': { '*id': 'str', '*node-name': 'str' } }
+
+##
+# @blockdev-open-tray:
+#
+# Opens a block device's tray. If there is a block driver state tree inserted as
+# a medium, it will become inaccessible to the guest (but it will remain
+# associated to the block device, so closing the tray will make it accessible
+# again).
+#
+# If the tray was already open before, this will be a no-op.
+#
+# Once the tray opens, a DEVICE_TRAY_MOVED event is emitted. There are cases in
+# which no such event will be generated, these include:
+# - if the guest has locked the tray, @force is false and the guest does not
+# respond to the eject request
+# - if the BlockBackend denoted by @device does not have a guest device attached
+# to it
+# - if the guest device does not have an actual tray
+#
+# @device: block device name
+#
+# @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
+# immediately); if true, the tray will be opened regardless of whether
+# it is locked
+#
+# Since: 2.5
+##
+{ 'command': 'blockdev-open-tray',
+ 'data': { 'device': 'str',
+ '*force': 'bool' } }
+
+##
+# @blockdev-close-tray:
+#
+# Closes a block device's tray. If there is a block driver state tree associated
+# with the block device (which is currently ejected), that tree will be loaded
+# as the medium.
+#
+# If the tray was already closed before, this will be a no-op.
+#
+# @device: block device name
+#
+# Since: 2.5
+##
+{ 'command': 'blockdev-close-tray',
+ 'data': { 'device': 'str' } }
+
+##
+# @x-blockdev-remove-medium:
+#
+# Removes a medium (a block driver state tree) from a block device. That block
+# device's tray must currently be open (unless there is no attached guest
+# device).
+#
+# If the tray is open and there is no medium inserted, this will be a no-op.
+#
+# 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
+#
+# Since: 2.5
+##
+{ 'command': 'x-blockdev-remove-medium',
+ 'data': { 'device': 'str' } }
+
+##
+# @x-blockdev-insert-medium:
+#
+# Inserts a medium (a block driver state tree) into a block device. That block
+# device's tray must currently be open (unless there is no attached guest
+# device) and there must be no medium inserted already.
+#
+# 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
+#
+# @node-name: name of a node in the block driver state graph
+#
+# Since: 2.5
+##
+{ 'command': 'x-blockdev-insert-medium',
+ 'data': { 'device': 'str',
+ 'node-name': 'str'} }
+
+
+##
+# @BlockdevChangeReadOnlyMode:
+#
+# Specifies the new read-only mode of a block device subject to the
+# @blockdev-change-medium command.
+#
+# @retain: Retains the current read-only mode
+#
+# @read-only: Makes the device read-only
+#
+# @read-write: Makes the device writable
+#
+# Since: 2.3
+##
+{ 'enum': 'BlockdevChangeReadOnlyMode',
+ 'data': ['retain', 'read-only', 'read-write'] }
+
+
+##
+# @blockdev-change-medium:
+#
+# Changes the medium inserted into a block device by ejecting the current medium
+# and loading a new image file which is inserted as the new medium (this command
+# combines blockdev-open-tray, x-blockdev-remove-medium,
+# x-blockdev-insert-medium and blockdev-close-tray).
+#
+# @device: block device name
+#
+# @filename: filename of the new image to be loaded
+#
+# @format: #optional, format to open the new image with (defaults to
+# the probed format)
+#
+# @read-only-mode: #optional, change the read-only mode of the device; defaults
+# to 'retain'
+#
+# Since: 2.5
+##
+{ 'command': 'blockdev-change-medium',
+ 'data': { 'device': 'str',
+ 'filename': 'str',
+ '*format': 'str',
+ '*read-only-mode': 'BlockdevChangeReadOnlyMode' } }
+
##
# @BlockErrorAction
diff --git a/qemu/qapi/block.json b/qemu/qapi/block.json
index aad645c4a..937337dce 100644
--- a/qemu/qapi/block.json
+++ b/qemu/qapi/block.json
@@ -6,7 +6,7 @@
{ 'include': 'block-core.json' }
##
-# BiosAtaTranslation:
+# @BiosAtaTranslation:
#
# Policy that BIOS should use to interpret cylinder/head/sector
# addresses. Note that Bochs BIOS and SeaBIOS will not actually
@@ -40,6 +40,22 @@
'data': ['auto', 'none', 'lba', 'large', 'rechs']}
##
+# @FloppyDriveType
+#
+# Type of Floppy drive to be emulated by the Floppy Disk Controller.
+#
+# @144: 1.44MB 3.5" drive
+# @288: 2.88MB 3.5" drive
+# @120: 1.2MB 5.25" drive
+# @none: No drive connected
+# @auto: Automatically determined by inserted media at boot
+#
+# Since: 2.6
+##
+{ 'enum': 'FloppyDriveType',
+ 'data': ['144', '288', '120', 'none', 'auto']}
+
+##
# @BlockdevSnapshotInternal
#
# @device: the name of the device to generate the snapshot from
@@ -130,13 +146,15 @@
# QEMU instance could refer to them as "nbd:HOST:PORT:exportname=NAME".
#
# @addr: Address on which to listen.
+# @tls-creds: (optional) ID of the TLS credentials object. Since 2.6
#
# Returns: error if the server is already running.
#
# Since: 1.3.0
##
{ 'command': 'nbd-server-start',
- 'data': { 'addr': 'SocketAddress' } }
+ 'data': { 'addr': 'SocketAddress',
+ '*tls-creds': 'str'} }
##
# @nbd-server-add:
@@ -178,3 +196,19 @@
##
{ 'event': 'DEVICE_TRAY_MOVED',
'data': { 'device': 'str', 'tray-open': 'bool' } }
+
+##
+# @QuorumOpType
+#
+# An enumeration of the quorum operation types
+#
+# @read: read operation
+#
+# @write: write operation
+#
+# @flush: flush operation
+#
+# Since: 2.6
+##
+{ 'enum': 'QuorumOpType',
+ 'data': [ 'read', 'write', 'flush' ] }
diff --git a/qemu/qapi/common.json b/qemu/qapi/common.json
index bad56bf68..9353a7b37 100644
--- a/qemu/qapi/common.json
+++ b/qemu/qapi/common.json
@@ -3,7 +3,7 @@
# QAPI common definitions
##
-# @ErrorClass
+# @QapiErrorClass
#
# QEMU error classes
#
@@ -24,7 +24,8 @@
#
# Since: 1.2
##
-{ 'enum': 'ErrorClass',
+{ 'enum': 'QapiErrorClass',
+ # Keep this in sync with ErrorClass in error.h
'data': [ 'GenericError', 'CommandNotFound', 'DeviceEncrypted',
'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap' ] }
@@ -114,3 +115,19 @@
##
{ 'enum': 'OnOffAuto',
'data': [ 'auto', 'on', 'off' ] }
+
+##
+# @OnOffSplit
+#
+# An enumeration of three values: on, off, and split
+#
+# @on: Enabled
+#
+# @off: Disabled
+#
+# @split: Mixed
+#
+# Since: 2.6
+##
+{ 'enum': 'OnOffSplit',
+ 'data': [ 'on', 'off', 'split' ] }
diff --git a/qemu/qapi/crypto.json b/qemu/qapi/crypto.json
new file mode 100644
index 000000000..760d0c057
--- /dev/null
+++ b/qemu/qapi/crypto.json
@@ -0,0 +1,222 @@
+# -*- Mode: Python -*-
+#
+# QAPI crypto definitions
+
+##
+# QCryptoTLSCredsEndpoint:
+#
+# The type of network endpoint that will be using the credentials.
+# Most types of credential require different setup / structures
+# depending on whether they will be used in a server versus a
+# client.
+#
+# @client: the network endpoint is acting as the client
+#
+# @server: the network endpoint is acting as the server
+#
+# Since: 2.5
+##
+{ 'enum': 'QCryptoTLSCredsEndpoint',
+ 'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT',
+ 'data': ['client', 'server']}
+
+
+##
+# QCryptoSecretFormat:
+#
+# The data format that the secret is provided in
+#
+# @raw: raw bytes. When encoded in JSON only valid UTF-8 sequences can be used
+# @base64: arbitrary base64 encoded binary data
+# Since: 2.6
+##
+{ 'enum': 'QCryptoSecretFormat',
+ 'prefix': 'QCRYPTO_SECRET_FORMAT',
+ 'data': ['raw', 'base64']}
+
+
+##
+# QCryptoHashAlgorithm:
+#
+# The supported algorithms for computing content digests
+#
+# @md5: MD5. Should not be used in any new code, legacy compat only
+# @sha1: SHA-1. Should not be used in any new code, legacy compat only
+# @sha256: SHA-256. Current recommended strong hash.
+# Since: 2.6
+##
+{ 'enum': 'QCryptoHashAlgorithm',
+ 'prefix': 'QCRYPTO_HASH_ALG',
+ 'data': ['md5', 'sha1', 'sha256']}
+
+
+##
+# QCryptoCipherAlgorithm:
+#
+# The supported algorithms for content encryption ciphers
+#
+# @aes-128: AES with 128 bit / 16 byte keys
+# @aes-192: AES with 192 bit / 24 byte keys
+# @aes-256: AES with 256 bit / 32 byte keys
+# @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
+# @cast5-128: Cast5 with 128 bit / 16 byte keys
+# @serpent-128: Serpent with 128 bit / 16 byte keys
+# @serpent-192: Serpent with 192 bit / 24 byte keys
+# @serpent-256: Serpent with 256 bit / 32 byte keys
+# @twofish-128: Twofish with 128 bit / 16 byte keys
+# @twofish-192: Twofish with 192 bit / 24 byte keys
+# @twofish-256: Twofish with 256 bit / 32 byte keys
+# Since: 2.6
+##
+{ 'enum': 'QCryptoCipherAlgorithm',
+ 'prefix': 'QCRYPTO_CIPHER_ALG',
+ 'data': ['aes-128', 'aes-192', 'aes-256',
+ 'des-rfb',
+ 'cast5-128',
+ 'serpent-128', 'serpent-192', 'serpent-256',
+ 'twofish-128', 'twofish-192', 'twofish-256']}
+
+
+##
+# 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
+# Since: 2.6
+##
+{ 'enum': 'QCryptoCipherMode',
+ 'prefix': 'QCRYPTO_CIPHER_MODE',
+ 'data': ['ecb', 'cbc', 'xts']}
+
+
+##
+# QCryptoIVGenAlgorithm:
+#
+# The supported algorithms for generating initialization
+# vectors for full disk encryption. The 'plain' generator
+# should not be used for disks with sector numbers larger
+# than 2^32, except where compatibility with pre-existing
+# Linux dm-crypt volumes is required.
+#
+# @plain: 64-bit sector number truncated to 32-bits
+# @plain64: 64-bit sector number
+# @essiv: 64-bit sector number encrypted with a hash of the encryption key
+# Since: 2.6
+##
+{ 'enum': 'QCryptoIVGenAlgorithm',
+ 'prefix': 'QCRYPTO_IVGEN_ALG',
+ 'data': ['plain', 'plain64', 'essiv']}
+
+##
+# QCryptoBlockFormat:
+#
+# The supported full disk encryption formats
+#
+# @qcow: QCow/QCow2 built-in AES-CBC encryption. Use only
+# for liberating data from old images.
+# @luks: LUKS encryption format. Recommended for new images
+#
+# Since: 2.6
+##
+{ 'enum': 'QCryptoBlockFormat',
+# 'prefix': 'QCRYPTO_BLOCK_FORMAT',
+ 'data': ['qcow', 'luks']}
+
+##
+# QCryptoBlockOptionsBase:
+#
+# The common options that apply to all full disk
+# encryption formats
+#
+# @format: the encryption format
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsBase',
+ 'data': { 'format': 'QCryptoBlockFormat' }}
+
+##
+# QCryptoBlockOptionsQCow:
+#
+# The options that apply to QCow/QCow2 AES-CBC encryption format
+#
+# @key-secret: #optional the ID of a QCryptoSecret object providing the
+# decryption key. Mandatory except when probing image for
+# metadata only.
+#
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsQCow',
+ 'data': { '*key-secret': 'str' }}
+
+##
+# QCryptoBlockOptionsLUKS:
+#
+# The options that apply to LUKS encryption format
+#
+# @key-secret: #optional the ID of a QCryptoSecret object providing the
+# decryption key. Mandatory except when probing image for
+# metadata only.
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockOptionsLUKS',
+ 'data': { '*key-secret': 'str' }}
+
+
+##
+# QCryptoBlockCreateOptionsLUKS:
+#
+# The options that apply to LUKS encryption format initialization
+#
+# @cipher-alg: #optional the cipher algorithm for data encryption
+# Currently defaults to 'aes'.
+# @cipher-mode: #optional the cipher mode for data encryption
+# Currently defaults to 'cbc'
+# @ivgen-alg: #optional the initialization vector generator
+# Currently defaults to 'essiv'
+# @ivgen-hash-alg: #optional the initialization vector generator hash
+# Currently defaults to 'sha256'
+# @hash-alg: #optional the master key hash algorithm
+# Currently defaults to 'sha256'
+# Since: 2.6
+##
+{ 'struct': 'QCryptoBlockCreateOptionsLUKS',
+ 'base': 'QCryptoBlockOptionsLUKS',
+ 'data': { '*cipher-alg': 'QCryptoCipherAlgorithm',
+ '*cipher-mode': 'QCryptoCipherMode',
+ '*ivgen-alg': 'QCryptoIVGenAlgorithm',
+ '*ivgen-hash-alg': 'QCryptoHashAlgorithm',
+ '*hash-alg': 'QCryptoHashAlgorithm'}}
+
+
+##
+# QCryptoBlockOpenOptions:
+#
+# The options that are available for all encryption formats
+# when opening an existing volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockOpenOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcow': 'QCryptoBlockOptionsQCow',
+ 'luks': 'QCryptoBlockOptionsLUKS' } }
+
+
+##
+# QCryptoBlockCreateOptions:
+#
+# The options that are available for all encryption formats
+# when initializing a new volume
+#
+# Since: 2.6
+##
+{ 'union': 'QCryptoBlockCreateOptions',
+ 'base': 'QCryptoBlockOptionsBase',
+ 'discriminator': 'format',
+ 'data': { 'qcow': 'QCryptoBlockOptionsQCow',
+ 'luks': 'QCryptoBlockCreateOptionsLUKS' } }
diff --git a/qemu/qapi/event.json b/qemu/qapi/event.json
index f0cef010f..8642052eb 100644
--- a/qemu/qapi/event.json
+++ b/qemu/qapi/event.json
@@ -255,6 +255,19 @@
'data': {'status': 'MigrationStatus'}}
##
+# @MIGRATION_PASS
+#
+# Emitted from the source side of a migration at the start of each pass
+# (when it syncs the dirty bitmap)
+#
+# @pass: An incrementing count (starting at 1 on the first pass)
+#
+# Since: 2.6
+##
+{ 'event': 'MIGRATION_PASS',
+ 'data': { 'pass': 'int' } }
+
+##
# @ACPI_DEVICE_OST
#
# Emitted when guest executes ACPI _OST method.
@@ -312,6 +325,8 @@
#
# Emitted to report a corruption of a Quorum file
#
+# @type: quorum operation type (Since 2.6)
+#
# @error: #optional, error message. Only present on failure. This field
# contains a human-readable error message. There are no semantics other
# than that the block layer reported an error and clients should not
@@ -326,7 +341,7 @@
# Since: 2.0
##
{ 'event': 'QUORUM_REPORT_BAD',
- 'data': { '*error': 'str', 'node-name': 'str',
+ 'data': { 'type': 'QuorumOpType', '*error': 'str', 'node-name': 'str',
'sector-num': 'int', 'sectors-count': 'int' } }
##
@@ -356,3 +371,19 @@
##
{ 'event': 'MEM_UNPLUG_ERROR',
'data': { 'device': 'str', 'msg': 'str' } }
+
+##
+# @DUMP_COMPLETED
+#
+# Emitted when background dump has completed
+#
+# @result: DumpQueryResult type described in qapi-schema.json.
+#
+# @error: #optional human-readable error string that provides
+# hint on why dump failed. Only presents on failure. The
+# user should not try to interpret the error string.
+#
+# Since: 2.6
+##
+{ 'event': 'DUMP_COMPLETED' ,
+ 'data': { 'result': 'DumpQueryResult', '*error': 'str' } }
diff --git a/qemu/qapi/introspect.json b/qemu/qapi/introspect.json
new file mode 100644
index 000000000..3fd81fb54
--- /dev/null
+++ b/qemu/qapi/introspect.json
@@ -0,0 +1,279 @@
+# -*- Mode: Python -*-
+#
+# QAPI/QMP introspection
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# Authors:
+# Markus Armbruster <armbru@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+
+##
+# @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
+# events are available in this QEMU, and their parameters and results.
+#
+# However, the SchemaInfo can't reflect all the rules and restrictions
+# that apply to QMP. It's interface introspection (figuring out
+# what's there), not interface specification. The specification is in
+# the QAPI schema.
+#
+# Furthermore, while we strive to keep the QMP wire format
+# backwards-compatible across qemu versions, the introspection output
+# is not guaranteed to have the same stability. For example, one
+# version of qemu may list an object member as an optional
+# non-variant, while another lists the same member only through the
+# object's variants; or the type of a member may change from a generic
+# string into a specific enum or from one specific type into an
+# alternate that includes the original type alongside something else.
+#
+# Returns: array of @SchemaInfo, where each element describes an
+# entity in the ABI: command, event, type, ...
+#
+# The order of the various SchemaInfo is unspecified; however, all
+# names are guaranteed to be unique (no name will be duplicated with
+# different meta-types).
+#
+# Note: the QAPI schema is also used to help define *internal*
+# interfaces, by defining QAPI types. These are not part of the QMP
+# wire ABI, and therefore not returned by this command.
+#
+# Since: 2.5
+##
+{ 'command': 'query-qmp-schema',
+ 'returns': [ 'SchemaInfo' ],
+ 'gen': false } # just to simplify qmp_query_json()
+
+##
+# @SchemaMetaType
+#
+# This is a @SchemaInfo's meta type, i.e. the kind of entity it
+# describes.
+#
+# @builtin: a predefined type such as 'int' or 'bool'.
+#
+# @enum: an enumeration type
+#
+# @array: an array type
+#
+# @object: an object type (struct or union)
+#
+# @alternate: an alternate type
+#
+# @command: a QMP command
+#
+# @event: a QMP event
+#
+# Since: 2.5
+##
+{ 'enum': 'SchemaMetaType',
+ 'data': [ 'builtin', 'enum', 'array', 'object', 'alternate',
+ 'command', 'event' ] }
+
+##
+# @SchemaInfo
+#
+# @name: the entity's name, inherited from @base.
+# Commands and events have the name defined in the QAPI schema.
+# Unlike command and event names, type names are not part of
+# the wire ABI. Consequently, type names are meaningless
+# strings here, although they are still guaranteed unique
+# regardless of @meta-type.
+#
+# All references to other SchemaInfo are by name.
+#
+# @meta-type: the entity's meta type, inherited from @base.
+#
+# Additional members depend on the value of @meta-type.
+#
+# Since: 2.5
+##
+{ 'union': 'SchemaInfo',
+ 'base': { 'name': 'str', 'meta-type': 'SchemaMetaType' },
+ 'discriminator': 'meta-type',
+ 'data': {
+ 'builtin': 'SchemaInfoBuiltin',
+ 'enum': 'SchemaInfoEnum',
+ 'array': 'SchemaInfoArray',
+ 'object': 'SchemaInfoObject',
+ 'alternate': 'SchemaInfoAlternate',
+ 'command': 'SchemaInfoCommand',
+ 'event': 'SchemaInfoEvent' } }
+
+##
+# @SchemaInfoBuiltin
+#
+# Additional SchemaInfo members for meta-type 'builtin'.
+#
+# @json-type: the JSON type used for this type on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoBuiltin',
+ 'data': { 'json-type': 'JSONType' } }
+
+##
+# @JSONType
+#
+# The four primitive and two structured types according to RFC 7159
+# section 1, plus 'int' (split off 'number'), plus the obvious top
+# type 'value'.
+#
+# Since: 2.5
+##
+{ 'enum': 'JSONType',
+ 'data': [ 'string', 'number', 'int', 'boolean', 'null',
+ 'object', 'array', 'value' ] }
+
+##
+# @SchemaInfoEnum
+#
+# Additional SchemaInfo members for meta-type 'enum'.
+#
+# @values: the enumeration type's values, in no particular order.
+#
+# Values of this type are JSON string on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoEnum',
+ 'data': { 'values': ['str'] } }
+
+##
+# @SchemaInfoArray
+#
+# Additional SchemaInfo members for meta-type 'array'.
+#
+# @element-type: the array type's element type.
+#
+# Values of this type are JSON array on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoArray',
+ 'data': { 'element-type': 'str' } }
+
+##
+# @SchemaInfoObject
+#
+# Additional SchemaInfo members for meta-type 'object'.
+#
+# @members: the object type's (non-variant) members, in no particular order.
+#
+# @tag: #optional the name of the member serving as type tag.
+# An element of @members with this name must exist.
+#
+# @variants: #optional variant members, i.e. additional members that
+# depend on the type tag's value. Present exactly when
+# @tag is present. The variants are in no particular order,
+# and may even differ from the order of the values of the
+# enum type of the @tag.
+#
+# Values of this type are JSON object on the wire.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObject',
+ 'data': { 'members': [ 'SchemaInfoObjectMember' ],
+ '*tag': 'str',
+ '*variants': [ 'SchemaInfoObjectVariant' ] } }
+
+##
+# @SchemaInfoObjectMember
+#
+# An object member.
+#
+# @name: the member's name, as defined in the QAPI schema.
+#
+# @type: the name of the member's type.
+#
+# @default: #optional default when used as command parameter.
+# If absent, the parameter is mandatory.
+# If present, the value must be null. The parameter is
+# optional, and behavior when it's missing is not specified
+# here.
+# Future extension: if present and non-null, the parameter
+# is optional, and defaults to this value.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObjectMember',
+ 'data': { 'name': 'str', 'type': 'str', '*default': 'any' } }
+# @default's type must be null or match @type
+
+##
+# @SchemaInfoObjectVariant
+#
+# The variant members for a value of the type tag.
+#
+# @case: a value of the type tag.
+#
+# @type: the name of the object type that provides the variant members
+# when the type tag has value @case.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoObjectVariant',
+ 'data': { 'case': 'str', 'type': 'str' } }
+
+##
+# @SchemaInfoAlternate
+#
+# Additional SchemaInfo members for meta-type 'alternate'.
+#
+# @members: the alternate type's members, in no particular order.
+# The members' wire encoding is distinct, see
+# docs/qapi-code-gen.txt section Alternate types.
+#
+# On the wire, this can be any of the members.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoAlternate',
+ 'data': { 'members': [ 'SchemaInfoAlternateMember' ] } }
+
+##
+# @SchemaInfoAlternateMember
+#
+# An alternate member.
+#
+# @type: the name of the member's type.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoAlternateMember',
+ 'data': { 'type': 'str' } }
+
+##
+# @SchemaInfoCommand
+#
+# Additional SchemaInfo members for meta-type 'command'.
+#
+# @arg-type: the name of the object type that provides the command's
+# parameters.
+#
+# @ret-type: the name of the command's result type.
+#
+# TODO @success-response (currently irrelevant, because it's QGA, not QMP)
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoCommand',
+ 'data': { 'arg-type': 'str', 'ret-type': 'str' } }
+
+##
+# @SchemaInfoEvent
+#
+# Additional SchemaInfo members for meta-type 'event'.
+#
+# @arg-type: the name of the object type that provides the event's
+# parameters.
+#
+# Since: 2.5
+##
+{ 'struct': 'SchemaInfoEvent',
+ 'data': { 'arg-type': 'str' } }
diff --git a/qemu/qapi/opts-visitor.c b/qemu/qapi/opts-visitor.c
index 7ae33b311..602f2609c 100644
--- a/qemu/qapi/opts-visitor.c
+++ b/qemu/qapi/opts-visitor.c
@@ -1,7 +1,7 @@
/*
* Options Visitor
*
- * Copyright Red Hat, Inc. 2012, 2013
+ * Copyright Red Hat, Inc. 2012-2016
*
* Author: Laszlo Ersek <lersek@redhat.com>
*
@@ -10,7 +10,9 @@
*
*/
-#include "qemu-common.h"
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
#include "qapi/qmp/qerror.h"
#include "qapi/opts-visitor.h"
#include "qemu/queue.h"
@@ -89,6 +91,12 @@ struct OptsVisitor
};
+static OptsVisitor *to_ov(Visitor *v)
+{
+ return container_of(v, OptsVisitor, visitor);
+}
+
+
static void
destroy_list(gpointer list)
{
@@ -118,10 +126,10 @@ opts_visitor_insert(GHashTable *unprocessed_opts, const QemuOpt *opt)
static void
-opts_start_struct(Visitor *v, void **obj, const char *kind,
- const char *name, size_t size, Error **errp)
+opts_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
if (obj) {
@@ -150,17 +158,11 @@ opts_start_struct(Visitor *v, void **obj, const char *kind,
}
-static gboolean
-ghr_true(gpointer ign_key, gpointer ign_value, gpointer ign_user_data)
-{
- return TRUE;
-}
-
-
static void
opts_end_struct(Visitor *v, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
+ GHashTableIter iter;
GQueue *any;
if (--ov->depth > 0) {
@@ -168,8 +170,8 @@ opts_end_struct(Visitor *v, Error **errp)
}
/* we should have processed all (distinct) QemuOpt instances */
- any = g_hash_table_find(ov->unprocessed_opts, &ghr_true, NULL);
- if (any) {
+ g_hash_table_iter_init(&iter, ov->unprocessed_opts);
+ if (g_hash_table_iter_next(&iter, NULL, (void **)&any)) {
const QemuOpt *first;
first = g_queue_peek_head(any);
@@ -202,7 +204,7 @@ lookup_distinct(const OptsVisitor *ov, const char *name, Error **errp)
static void
opts_start_list(Visitor *v, const char *name, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
/* we can't traverse a list in a list */
assert(ov->list_mode == LM_NONE);
@@ -214,9 +216,9 @@ opts_start_list(Visitor *v, const char *name, Error **errp)
static GenericList *
-opts_next_list(Visitor *v, GenericList **list, Error **errp)
+opts_next_list(Visitor *v, GenericList **list, size_t size)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
GenericList **link;
switch (ov->list_mode) {
@@ -257,15 +259,15 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp)
abort();
}
- *link = g_malloc0(sizeof **link);
+ *link = g_malloc0(size);
return *link;
}
static void
-opts_end_list(Visitor *v, Error **errp)
+opts_end_list(Visitor *v)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
assert(ov->list_mode == LM_STARTED ||
ov->list_mode == LM_IN_PROGRESS ||
@@ -305,9 +307,9 @@ processed(OptsVisitor *ov, const char *name)
static void
-opts_type_str(Visitor *v, char **obj, const char *name, Error **errp)
+opts_type_str(Visitor *v, const char *name, char **obj, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
opt = lookup_scalar(ov, name, errp);
@@ -321,9 +323,9 @@ opts_type_str(Visitor *v, char **obj, const char *name, Error **errp)
/* mimics qemu-option.c::parse_option_bool() */
static void
-opts_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
+opts_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
opt = lookup_scalar(ov, name, errp);
@@ -354,9 +356,9 @@ opts_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
static void
-opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
+opts_type_int64(Visitor *v, const char *name, int64_t *obj, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
const char *str;
long long val;
@@ -410,9 +412,9 @@ opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
static void
-opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+opts_type_uint64(Visitor *v, const char *name, uint64_t *obj, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
const char *str;
unsigned long long val;
@@ -462,9 +464,9 @@ opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
static void
-opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+opts_type_size(Visitor *v, const char *name, uint64_t *obj, Error **errp)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
const QemuOpt *opt;
int64_t val;
char *endptr;
@@ -474,8 +476,8 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
return;
}
- val = strtosz_suffix(opt->str ? opt->str : "", &endptr,
- STRTOSZ_DEFSUFFIX_B);
+ val = qemu_strtosz_suffix(opt->str ? opt->str : "", &endptr,
+ QEMU_STRTOSZ_DEFSUFFIX_B);
if (val < 0 || *endptr) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
"a size value representible as a non-negative int64");
@@ -488,9 +490,9 @@ opts_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
static void
-opts_optional(Visitor *v, bool *present, const char *name, Error **errp)
+opts_optional(Visitor *v, const char *name, bool *present)
{
- OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ OptsVisitor *ov = to_ov(v);
/* we only support a single mandatory scalar field in a list node */
assert(ov->list_mode == LM_NONE);
@@ -522,7 +524,7 @@ opts_visitor_new(const QemuOpts *opts)
*/
ov->visitor.type_enum = &input_type_enum;
- ov->visitor.type_int = &opts_type_int;
+ ov->visitor.type_int64 = &opts_type_int64;
ov->visitor.type_uint64 = &opts_type_uint64;
ov->visitor.type_size = &opts_type_size;
ov->visitor.type_bool = &opts_type_bool;
diff --git a/qemu/qapi/qapi-dealloc-visitor.c b/qemu/qapi/qapi-dealloc-visitor.c
index d7f92c5d6..69221794e 100644
--- a/qemu/qapi/qapi-dealloc-visitor.c
+++ b/qemu/qapi/qapi-dealloc-visitor.c
@@ -1,6 +1,7 @@
/*
* Dealloc Visitor
*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
* Copyright IBM, Corp. 2011
*
* Authors:
@@ -11,6 +12,7 @@
*
*/
+#include "qemu/osdep.h"
#include "qapi/dealloc-visitor.h"
#include "qemu/queue.h"
#include "qemu-common.h"
@@ -28,7 +30,6 @@ struct QapiDeallocVisitor
{
Visitor visitor;
QTAILQ_HEAD(, StackEntry) stack;
- bool is_list_head;
};
static QapiDeallocVisitor *to_qov(Visitor *v)
@@ -59,9 +60,8 @@ static void *qapi_dealloc_pop(QapiDeallocVisitor *qov)
return value;
}
-static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind,
- const char *name, size_t unused,
- Error **errp)
+static void qapi_dealloc_start_struct(Visitor *v, const char *name, void **obj,
+ size_t unused, Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
qapi_dealloc_push(qov, obj);
@@ -76,16 +76,15 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
}
}
-static void qapi_dealloc_start_implicit_struct(Visitor *v,
- void **obj,
- size_t size,
- Error **errp)
+static void qapi_dealloc_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ bool promote_int, Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
qapi_dealloc_push(qov, obj);
}
-static void qapi_dealloc_end_implicit_struct(Visitor *v, Error **errp)
+static void qapi_dealloc_end_alternate(Visitor *v)
{
QapiDeallocVisitor *qov = to_qov(v);
void **obj = qapi_dealloc_pop(qov);
@@ -101,7 +100,7 @@ static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
}
static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
- Error **errp)
+ size_t size)
{
GenericList *list = *listp;
QapiDeallocVisitor *qov = to_qov(v);
@@ -121,14 +120,14 @@ static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
return NULL;
}
-static void qapi_dealloc_end_list(Visitor *v, Error **errp)
+static void qapi_dealloc_end_list(Visitor *v)
{
QapiDeallocVisitor *qov = to_qov(v);
void *obj = qapi_dealloc_pop(qov);
assert(obj == NULL); /* should've been list head tracker with no payload */
}
-static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
+static void qapi_dealloc_type_str(Visitor *v, const char *name, char **obj,
Error **errp)
{
if (obj) {
@@ -136,56 +135,37 @@ static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
}
}
-static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,
- Error **errp)
+static void qapi_dealloc_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
}
-static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name,
- Error **errp)
+static void qapi_dealloc_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
{
}
-static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
- Error **errp)
+static void qapi_dealloc_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
{
}
-static void qapi_dealloc_type_size(Visitor *v, uint64_t *obj, const char *name,
- Error **errp)
+static void qapi_dealloc_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
{
}
-static void qapi_dealloc_type_enum(Visitor *v, int *obj,
- const char * const strings[],
- const char *kind, const char *name,
- Error **errp)
+static void qapi_dealloc_type_anything(Visitor *v, const char *name,
+ QObject **obj, Error **errp)
{
+ if (obj) {
+ qobject_decref(*obj);
+ }
}
-/* If there's no data present, the dealloc visitor has nothing to free.
- * Thus, indicate to visitor code that the subsequent union fields can
- * be skipped. This is not an error condition, since the cleanup of the
- * rest of an object can continue unhindered, so leave errp unset in
- * these cases.
- *
- * NOTE: In cases where we're attempting to deallocate an object that
- * may have missing fields, the field indicating the union type may
- * be missing. In such a case, it's possible we don't have enough
- * information to differentiate data_present == false from a case where
- * data *is* present but happens to be a scalar with a value of 0.
- * This is okay, since in the case of the dealloc visitor there's no
- * work that needs to done in either situation.
- *
- * The current inability in QAPI code to more thoroughly verify a union
- * type in such cases will likely need to be addressed if we wish to
- * implement this interface for other types of visitors in the future,
- * however.
- */
-static bool qapi_dealloc_start_union(Visitor *v, bool data_present,
- Error **errp)
+static void qapi_dealloc_type_enum(Visitor *v, const char *name, int *obj,
+ const char * const strings[], Error **errp)
{
- return data_present;
}
Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
@@ -206,18 +186,18 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
v->visitor.start_struct = qapi_dealloc_start_struct;
v->visitor.end_struct = qapi_dealloc_end_struct;
- v->visitor.start_implicit_struct = qapi_dealloc_start_implicit_struct;
- v->visitor.end_implicit_struct = qapi_dealloc_end_implicit_struct;
+ v->visitor.start_alternate = qapi_dealloc_start_alternate;
+ v->visitor.end_alternate = qapi_dealloc_end_alternate;
v->visitor.start_list = qapi_dealloc_start_list;
v->visitor.next_list = qapi_dealloc_next_list;
v->visitor.end_list = qapi_dealloc_end_list;
v->visitor.type_enum = qapi_dealloc_type_enum;
- v->visitor.type_int = qapi_dealloc_type_int;
+ v->visitor.type_int64 = qapi_dealloc_type_int64;
+ v->visitor.type_uint64 = qapi_dealloc_type_uint64;
v->visitor.type_bool = qapi_dealloc_type_bool;
v->visitor.type_str = qapi_dealloc_type_str;
v->visitor.type_number = qapi_dealloc_type_number;
- v->visitor.type_size = qapi_dealloc_type_size;
- v->visitor.start_union = qapi_dealloc_start_union;
+ v->visitor.type_any = qapi_dealloc_type_anything;
QTAILQ_INIT(&v->stack);
diff --git a/qemu/qapi/qapi-util.c b/qemu/qapi/qapi-util.c
index bcdc94d5a..818730a66 100644
--- a/qemu/qapi/qapi-util.c
+++ b/qemu/qapi/qapi-util.c
@@ -10,8 +10,9 @@
*
*/
-#include "qemu-common.h"
+#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu-common.h"
#include "qapi/util.h"
int qapi_enum_parse(const char * const lookup[], const char *buf,
diff --git a/qemu/qapi/qapi-visit-core.c b/qemu/qapi/qapi-visit-core.c
index 5a7c90050..fa680c999 100644
--- a/qemu/qapi/qapi-visit-core.c
+++ b/qemu/qapi/qapi-visit-core.c
@@ -1,6 +1,7 @@
/*
* Core Definitions for QAPI Visitor Classes
*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
* Copyright IBM, Corp. 2011
*
* Authors:
@@ -11,16 +12,18 @@
*
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu-common.h"
#include "qapi/qmp/qobject.h"
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
-void visit_start_struct(Visitor *v, void **obj, const char *kind,
- const char *name, size_t size, Error **errp)
+void visit_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
{
- v->start_struct(v, obj, kind, name, size, errp);
+ v->start_struct(v, name, obj, size, errp);
}
void visit_end_struct(Visitor *v, Error **errp)
@@ -28,241 +31,185 @@ void visit_end_struct(Visitor *v, Error **errp)
v->end_struct(v, errp);
}
-void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
- Error **errp)
-{
- if (v->start_implicit_struct) {
- v->start_implicit_struct(v, obj, size, errp);
- }
-}
-
-void visit_end_implicit_struct(Visitor *v, Error **errp)
-{
- if (v->end_implicit_struct) {
- v->end_implicit_struct(v, errp);
- }
-}
-
void visit_start_list(Visitor *v, const char *name, Error **errp)
{
v->start_list(v, name, errp);
}
-GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
+GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
{
- return v->next_list(v, list, errp);
+ assert(list && size >= sizeof(GenericList));
+ return v->next_list(v, list, size);
}
-void visit_end_list(Visitor *v, Error **errp)
+void visit_end_list(Visitor *v)
{
- v->end_list(v, errp);
+ v->end_list(v);
}
-bool visit_start_union(Visitor *v, bool data_present, Error **errp)
+void visit_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ bool promote_int, Error **errp)
{
- if (v->start_union) {
- return v->start_union(v, data_present, errp);
+ assert(obj && size >= sizeof(GenericAlternate));
+ if (v->start_alternate) {
+ v->start_alternate(v, name, obj, size, promote_int, errp);
}
- return true;
}
-void visit_end_union(Visitor *v, bool data_present, Error **errp)
+void visit_end_alternate(Visitor *v)
{
- if (v->end_union) {
- v->end_union(v, data_present, errp);
+ if (v->end_alternate) {
+ v->end_alternate(v);
}
}
-void visit_optional(Visitor *v, bool *present, const char *name,
- Error **errp)
+bool visit_optional(Visitor *v, const char *name, bool *present)
{
if (v->optional) {
- v->optional(v, present, name, errp);
+ v->optional(v, name, present);
}
+ return *present;
}
-void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
- const char *name, Error **errp)
+void visit_type_enum(Visitor *v, const char *name, int *obj,
+ const char *const strings[], Error **errp)
{
- if (v->get_next_type) {
- v->get_next_type(v, obj, qtypes, name, errp);
- }
-}
-
-void visit_type_enum(Visitor *v, int *obj, const char * const strings[],
- const char *kind, const char *name, Error **errp)
-{
- v->type_enum(v, obj, strings, kind, name, errp);
+ v->type_enum(v, name, obj, strings, errp);
}
-void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
+void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
{
- v->type_int(v, obj, name, errp);
+ v->type_int64(v, name, obj, errp);
}
-void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp)
+static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
+ uint64_t max, const char *type, Error **errp)
{
- int64_t value;
-
- if (v->type_uint8) {
- v->type_uint8(v, obj, name, errp);
+ Error *err = NULL;
+ uint64_t value = *obj;
+
+ v->type_uint64(v, name, &value, &err);
+ if (err) {
+ error_propagate(errp, err);
+ } else if (value > max) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", type);
} else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT8_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint8_t");
- return;
- }
*obj = value;
}
}
-void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp)
+void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
+ Error **errp)
{
- int64_t value;
-
- if (v->type_uint16) {
- v->type_uint16(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT16_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint16_t");
- return;
- }
- *obj = value;
- }
+ uint64_t value = *obj;
+ visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
+ *obj = value;
}
-void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp)
+void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
+ Error **errp)
{
- int64_t value;
-
- if (v->type_uint32) {
- v->type_uint32(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < 0 || value > UINT32_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "uint32_t");
- return;
- }
- *obj = value;
- }
+ uint64_t value = *obj;
+ visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
+ *obj = value;
}
-void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
+ Error **errp)
{
- int64_t value;
-
- if (v->type_uint64) {
- v->type_uint64(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- *obj = value;
- }
+ uint64_t value = *obj;
+ visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
+ *obj = value;
}
-void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp)
+void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
{
- int64_t value;
-
- if (v->type_int8) {
- v->type_int8(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT8_MIN || value > INT8_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int8_t");
- return;
- }
- *obj = value;
- }
+ v->type_uint64(v, name, obj, errp);
}
-void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp)
+static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
+ int64_t min, int64_t max, const char *type,
+ Error **errp)
{
- int64_t value;
-
- if (v->type_int16) {
- v->type_int16(v, obj, name, errp);
+ Error *err = NULL;
+ int64_t value = *obj;
+
+ v->type_int64(v, name, &value, &err);
+ if (err) {
+ error_propagate(errp, err);
+ } else if (value < min || value > max) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", type);
} else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT16_MIN || value > INT16_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int16_t");
- return;
- }
*obj = value;
}
}
-void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)
+void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
{
- int64_t value;
+ int64_t value = *obj;
+ visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
+ *obj = value;
+}
- if (v->type_int32) {
- v->type_int32(v, obj, name, errp);
- } else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- if (value < INT32_MIN || value > INT32_MAX) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
- name ? name : "null", "int32_t");
- return;
- }
- *obj = value;
- }
+void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
+ Error **errp)
+{
+ int64_t value = *obj;
+ visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
+ *obj = value;
}
-void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
+void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
+ Error **errp)
{
- if (v->type_int64) {
- v->type_int64(v, obj, name, errp);
- } else {
- v->type_int(v, obj, name, errp);
- }
+ int64_t value = *obj;
+ visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
+ *obj = value;
}
-void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
+void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
- int64_t value;
+ v->type_int64(v, name, obj, errp);
+}
+void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
if (v->type_size) {
- v->type_size(v, obj, name, errp);
- } else if (v->type_uint64) {
- v->type_uint64(v, obj, name, errp);
+ v->type_size(v, name, obj, errp);
} else {
- value = *obj;
- v->type_int(v, &value, name, errp);
- *obj = value;
+ v->type_uint64(v, name, obj, errp);
}
}
-void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
+void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
{
- v->type_bool(v, obj, name, errp);
+ v->type_bool(v, name, obj, errp);
}
-void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
+void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
{
- v->type_str(v, obj, name, errp);
+ v->type_str(v, name, obj, errp);
}
-void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
+void visit_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
{
- v->type_number(v, obj, name, errp);
+ v->type_number(v, name, obj, errp);
}
-void output_type_enum(Visitor *v, int *obj, const char * const strings[],
- const char *kind, const char *name,
- Error **errp)
+void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
+{
+ v->type_any(v, name, obj, errp);
+}
+
+void output_type_enum(Visitor *v, const char *name, int *obj,
+ const char *const strings[], Error **errp)
{
int i = 0;
int value = *obj;
@@ -276,12 +223,11 @@ void output_type_enum(Visitor *v, int *obj, const char * const strings[],
}
enum_str = (char *)strings[value];
- visit_type_str(v, &enum_str, name, errp);
+ visit_type_str(v, name, &enum_str, errp);
}
-void input_type_enum(Visitor *v, int *obj, const char * const strings[],
- const char *kind, const char *name,
- Error **errp)
+void input_type_enum(Visitor *v, const char *name, int *obj,
+ const char *const strings[], Error **errp)
{
Error *local_err = NULL;
int64_t value = 0;
@@ -289,7 +235,7 @@ void input_type_enum(Visitor *v, int *obj, const char * const strings[],
assert(strings);
- visit_type_str(v, &enum_str, name, &local_err);
+ visit_type_str(v, name, &enum_str, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
diff --git a/qemu/qapi/qmp-dispatch.c b/qemu/qapi/qmp-dispatch.c
index 7bcc86080..510a1aead 100644
--- a/qemu/qapi/qmp-dispatch.c
+++ b/qemu/qapi/qmp-dispatch.c
@@ -11,11 +11,12 @@
*
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qapi/qmp/types.h"
#include "qapi/qmp/dispatch.h"
#include "qapi/qmp/json-parser.h"
#include "qapi-types.h"
-#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
@@ -114,7 +115,7 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp)
QObject *qmp_build_error_object(Error *err)
{
return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
- ErrorClass_lookup[error_get_class(err)],
+ QapiErrorClass_lookup[error_get_class(err)],
error_get_pretty(err));
}
diff --git a/qemu/qapi/qmp-event.c b/qemu/qapi/qmp-event.c
index 0d1ce0bd1..8bba165bf 100644
--- a/qemu/qapi/qmp-event.c
+++ b/qemu/qapi/qmp-event.c
@@ -11,21 +11,13 @@
*
*/
-#include <inttypes.h>
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qapi/qmp-event.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qjson.h"
-#ifdef _WIN32
-#include "sysemu/os-win32.h"
-#endif
-
-#ifdef CONFIG_POSIX
-#include "sysemu/os-posix.h"
-#endif
-
static QMPEventFuncEmit qmp_emit;
void qmp_event_set_func_emit(QMPEventFuncEmit emit)
diff --git a/qemu/qapi/qmp-input-visitor.c b/qemu/qapi/qmp-input-visitor.c
index e97b8a428..7cd1b777a 100644
--- a/qemu/qapi/qmp-input-visitor.c
+++ b/qemu/qapi/qmp-input-visitor.c
@@ -1,6 +1,7 @@
/*
* Input Visitor
*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
* Copyright IBM, Corp. 2011
*
* Authors:
@@ -11,6 +12,8 @@
*
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/visitor-impl.h"
#include "qemu/queue.h"
@@ -88,12 +91,6 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
qiv->nb_stack++;
}
-/** Only for qmp_input_pop. */
-static gboolean always_true(gpointer key, gpointer val, gpointer user_pkey)
-{
- *(const char **)user_pkey = (const char *)key;
- return TRUE;
-}
static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
{
@@ -102,9 +99,11 @@ static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
if (qiv->strict) {
GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
if (top_ht) {
- if (g_hash_table_size(top_ht)) {
- const char *key;
- g_hash_table_find(top_ht, always_true, &key);
+ GHashTableIter iter;
+ const char *key;
+
+ g_hash_table_iter_init(&iter, top_ht);
+ if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
error_setg(errp, QERR_QMP_EXTRA_MEMBER, key);
}
g_hash_table_unref(top_ht);
@@ -114,8 +113,8 @@ static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
qiv->nb_stack--;
}
-static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
- const char *name, size_t size, Error **errp)
+static void qmp_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);
@@ -145,18 +144,6 @@ static void qmp_input_end_struct(Visitor *v, Error **errp)
qmp_input_pop(qiv, errp);
}
-static void qmp_input_start_implicit_struct(Visitor *v, void **obj,
- size_t size, Error **errp)
-{
- if (obj) {
- *obj = g_malloc0(size);
- }
-}
-
-static void qmp_input_end_implicit_struct(Visitor *v, Error **errp)
-{
-}
-
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
@@ -172,7 +159,7 @@ static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
}
static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
- Error **errp)
+ size_t size)
{
QmpInputVisitor *qiv = to_qiv(v);
GenericList *entry;
@@ -191,7 +178,7 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
return NULL;
}
- entry = g_malloc0(sizeof(*entry));
+ entry = g_malloc0(size);
if (first) {
*list = entry;
} else {
@@ -201,97 +188,132 @@ static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
return entry;
}
-static void qmp_input_end_list(Visitor *v, Error **errp)
+static void qmp_input_end_list(Visitor *v)
{
QmpInputVisitor *qiv = to_qiv(v);
- qmp_input_pop(qiv, errp);
+ qmp_input_pop(qiv, &error_abort);
}
-static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
- const char *name, Error **errp)
+static void qmp_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);
if (!qobj) {
+ *obj = NULL;
error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
return;
}
- *kind = qobjects[qobject_type(qobj)];
+ *obj = g_malloc0(size);
+ (*obj)->type = qobject_type(qobj);
+ if (promote_int && (*obj)->type == QTYPE_QINT) {
+ (*obj)->type = QTYPE_QFLOAT;
+ }
}
-static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
- Error **errp)
+static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
- if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
+ if (!qint) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"integer");
return;
}
- *obj = qint_get_int(qobject_to_qint(qobj));
+ *obj = qint_get_int(qint);
}
-static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
+static void qmp_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));
+
+ if (!qint) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "integer");
+ return;
+ }
+
+ *obj = qint_get_int(qint);
+}
+
+static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true));
- if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
+ if (!qbool) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"boolean");
return;
}
- *obj = qbool_get_bool(qobject_to_qbool(qobj));
+ *obj = qbool_get_bool(qbool);
}
-static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
+static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true);
+ QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));
- if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
+ if (!qstr) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"string");
return;
}
- *obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj)));
+ *obj = g_strdup(qstring_get_str(qstr));
}
-static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
+static void qmp_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);
+ QInt *qint;
+ QFloat *qfloat;
- if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT &&
- qobject_type(qobj) != QTYPE_QINT)) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "number");
+ qint = qobject_to_qint(qobj);
+ if (qint) {
+ *obj = qint_get_int(qobject_to_qint(qobj));
return;
}
- if (qobject_type(qobj) == QTYPE_QINT) {
- *obj = qint_get_int(qobject_to_qint(qobj));
- } else {
+ qfloat = qobject_to_qfloat(qobj);
+ if (qfloat) {
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
+ return;
}
+
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "number");
}
-static void qmp_input_optional(Visitor *v, bool *present, const char *name,
+static void qmp_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);
+ qobject_incref(qobj);
+ *obj = qobj;
+}
+
+static void qmp_input_optional(Visitor *v, const char *name, bool *present)
+{
+ QmpInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
+
if (!qobj) {
*present = false;
return;
@@ -319,18 +341,18 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
v->visitor.start_struct = qmp_input_start_struct;
v->visitor.end_struct = qmp_input_end_struct;
- v->visitor.start_implicit_struct = qmp_input_start_implicit_struct;
- v->visitor.end_implicit_struct = qmp_input_end_implicit_struct;
v->visitor.start_list = qmp_input_start_list;
v->visitor.next_list = qmp_input_next_list;
v->visitor.end_list = qmp_input_end_list;
+ v->visitor.start_alternate = qmp_input_start_alternate;
v->visitor.type_enum = input_type_enum;
- v->visitor.type_int = qmp_input_type_int;
+ 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.optional = qmp_input_optional;
- v->visitor.get_next_type = qmp_input_get_next_type;
qmp_input_push(v, obj, NULL);
qobject_incref(obj);
diff --git a/qemu/qapi/qmp-output-visitor.c b/qemu/qapi/qmp-output-visitor.c
index efc19d584..d44c67631 100644
--- a/qemu/qapi/qmp-output-visitor.c
+++ b/qemu/qapi/qmp-output-visitor.c
@@ -1,6 +1,7 @@
/*
* Core Definitions for QAPI/QMP Command Registry
*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
* Copyright IBM, Corp. 2011
*
* Authors:
@@ -11,6 +12,7 @@
*
*/
+#include "qemu/osdep.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/visitor-impl.h"
#include "qemu/queue.h"
@@ -29,7 +31,8 @@ typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
struct QmpOutputVisitor
{
Visitor visitor;
- QStack stack;
+ QStack stack; /* Stack of containers that haven't yet been finished */
+ QObject *root; /* Root of the output visit */
};
#define qmp_output_add(qov, name, value) \
@@ -41,10 +44,13 @@ 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)
{
QStackEntry *e = g_malloc0(sizeof(*e));
+ assert(qov->root);
+ assert(value);
e->value = value;
if (qobject_type(e->value) == QTYPE_QLIST) {
e->is_list_head = true;
@@ -52,63 +58,51 @@ static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
QTAILQ_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)
{
QStackEntry *e = QTAILQ_FIRST(&qov->stack);
QObject *value;
+
+ assert(e);
QTAILQ_REMOVE(&qov->stack, e, node);
value = e->value;
+ assert(value);
g_free(e);
return value;
}
-static QObject *qmp_output_first(QmpOutputVisitor *qov)
-{
- QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
-
- /* FIXME - find a better way to deal with NULL values */
- if (!e) {
- return NULL;
- }
-
- return e->value;
-}
-
-static QObject *qmp_output_last(QmpOutputVisitor *qov)
-{
- QStackEntry *e = QTAILQ_FIRST(&qov->stack);
- return e->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)
{
- QObject *cur;
-
- if (QTAILQ_EMPTY(&qov->stack)) {
- qmp_output_push_obj(qov, value);
- return;
- }
+ QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+ QObject *cur = e ? e->value : NULL;
- cur = qmp_output_last(qov);
-
- switch (qobject_type(cur)) {
- case QTYPE_QDICT:
- qdict_put_obj(qobject_to_qdict(cur), name, value);
- break;
- case QTYPE_QLIST:
- qlist_append_obj(qobject_to_qlist(cur), value);
- break;
- default:
- qobject_decref(qmp_output_pop(qov));
- qmp_output_push_obj(qov, value);
- break;
+ if (!cur) {
+ /* FIXME we should require the user to reset the visitor, rather
+ * than throwing away the previous root */
+ qobject_decref(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:
+ qlist_append_obj(qobject_to_qlist(cur), value);
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
}
-static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind,
- const char *name, size_t unused,
- Error **errp)
+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();
@@ -133,7 +127,7 @@ static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
}
static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
- Error **errp)
+ size_t size)
{
GenericList *list = *listp;
QmpOutputVisitor *qov = to_qov(v);
@@ -148,27 +142,35 @@ static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
return list ? list->next : NULL;
}
-static void qmp_output_end_list(Visitor *v, Error **errp)
+static void qmp_output_end_list(Visitor *v)
{
QmpOutputVisitor *qov = to_qov(v);
qmp_output_pop(qov);
}
-static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name,
- Error **errp)
+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, bool *obj, const char *name,
+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, char **obj, const char *name,
+static void qmp_output_type_str(Visitor *v, const char *name, char **obj,
Error **errp)
{
QmpOutputVisitor *qov = to_qov(v);
@@ -179,18 +181,31 @@ static void qmp_output_type_str(Visitor *v, char **obj, const char *name,
}
}
-static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
+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);
+}
+
+/* Finish building, and return the root object. Will not be NULL. */
QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
{
- QObject *obj = qmp_output_first(qov);
+ /* FIXME: we should require that a visit occurred, and that it is
+ * complete (no starts without a matching end) */
+ QObject *obj = qov->root;
if (obj) {
qobject_incref(obj);
+ } else {
+ obj = qnull();
}
return obj;
}
@@ -204,16 +219,12 @@ void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
{
QStackEntry *e, *tmp;
- /* The bottom QStackEntry, if any, owns the root QObject. See the
- * qmp_output_push_obj() invocations in qmp_output_add_obj(). */
- QObject *root = QTAILQ_EMPTY(&v->stack) ? NULL : qmp_output_first(v);
-
QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
QTAILQ_REMOVE(&v->stack, e, node);
g_free(e);
}
- qobject_decref(root);
+ qobject_decref(v->root);
g_free(v);
}
@@ -229,10 +240,12 @@ QmpOutputVisitor *qmp_output_visitor_new(void)
v->visitor.next_list = qmp_output_next_list;
v->visitor.end_list = qmp_output_end_list;
v->visitor.type_enum = output_type_enum;
- v->visitor.type_int = qmp_output_type_int;
+ 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;
QTAILQ_INIT(&v->stack);
diff --git a/qemu/qapi/qmp-registry.c b/qemu/qapi/qmp-registry.c
index 3e4498a3f..4ebfbccd4 100644
--- a/qemu/qapi/qmp-registry.c
+++ b/qemu/qapi/qmp-registry.c
@@ -12,8 +12,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "qapi/qmp/dispatch.h"
static QTAILQ_HEAD(QmpCommandList, QmpCommand) qmp_commands =
diff --git a/qemu/qapi/string-input-visitor.c b/qemu/qapi/string-input-visitor.c
index bbd6a5456..5ea2d77b5 100644
--- a/qemu/qapi/string-input-visitor.c
+++ b/qemu/qapi/string-input-visitor.c
@@ -1,7 +1,7 @@
/*
* String parsing visitor
*
- * Copyright Red Hat, Inc. 2012
+ * Copyright Red Hat, Inc. 2012-2016
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
@@ -10,6 +10,8 @@
*
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu-common.h"
#include "qapi/string-input-visitor.h"
#include "qapi/visitor-impl.h"
@@ -32,6 +34,11 @@ struct StringInputVisitor
const char *string;
};
+static StringInputVisitor *to_siv(Visitor *v)
+{
+ return container_of(v, StringInputVisitor, visitor);
+}
+
static void free_range(void *range, void *dummy)
{
g_free(range);
@@ -120,7 +127,7 @@ error:
static void
start_list(Visitor *v, const char *name, Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
parse_str(siv, errp);
@@ -133,10 +140,9 @@ start_list(Visitor *v, const char *name, Error **errp)
}
}
-static GenericList *
-next_list(Visitor *v, GenericList **list, Error **errp)
+static GenericList *next_list(Visitor *v, GenericList **list, size_t size)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
GenericList **link;
Range *r;
@@ -168,21 +174,20 @@ next_list(Visitor *v, GenericList **list, Error **errp)
link = &(*list)->next;
}
- *link = g_malloc0(sizeof **link);
+ *link = g_malloc0(size);
return *link;
}
-static void
-end_list(Visitor *v, Error **errp)
+static void end_list(Visitor *v)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
siv->head = true;
}
-static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
- Error **errp)
+static void parse_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
if (!siv->string) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -217,14 +222,28 @@ static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
return;
error:
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
"an int64 value or range");
}
-static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
+static void parse_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ /* FIXME: parse_type_int64 mishandles values over INT64_MAX */
+ int64_t i;
+ Error *err = NULL;
+ parse_type_int64(v, name, &i, &err);
+ if (err) {
+ error_propagate(errp, err);
+ } else {
+ *obj = i;
+ }
+}
+
+static void parse_type_size(Visitor *v, const char *name, uint64_t *obj,
Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
Error *err = NULL;
uint64_t val;
@@ -243,10 +262,10 @@ static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
*obj = val;
}
-static void parse_type_bool(Visitor *v, bool *obj, const char *name,
+static void parse_type_bool(Visitor *v, const char *name, bool *obj,
Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
if (siv->string) {
if (!strcasecmp(siv->string, "on") ||
@@ -267,10 +286,10 @@ static void parse_type_bool(Visitor *v, bool *obj, const char *name,
"boolean");
}
-static void parse_type_str(Visitor *v, char **obj, const char *name,
+static void parse_type_str(Visitor *v, const char *name, char **obj,
Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
if (siv->string) {
*obj = g_strdup(siv->string);
} else {
@@ -279,10 +298,10 @@ static void parse_type_str(Visitor *v, char **obj, const char *name,
}
}
-static void parse_type_number(Visitor *v, double *obj, const char *name,
+static void parse_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
char *endp = (char *) siv->string;
double val;
@@ -299,10 +318,9 @@ static void parse_type_number(Visitor *v, double *obj, const char *name,
*obj = val;
}
-static void parse_optional(Visitor *v, bool *present, const char *name,
- Error **errp)
+static void parse_optional(Visitor *v, const char *name, bool *present)
{
- StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ StringInputVisitor *siv = to_siv(v);
if (!siv->string) {
*present = false;
@@ -331,7 +349,8 @@ StringInputVisitor *string_input_visitor_new(const char *str)
v = g_malloc0(sizeof(*v));
v->visitor.type_enum = input_type_enum;
- v->visitor.type_int = parse_type_int;
+ v->visitor.type_int64 = parse_type_int64;
+ v->visitor.type_uint64 = parse_type_uint64;
v->visitor.type_size = parse_type_size;
v->visitor.type_bool = parse_type_bool;
v->visitor.type_str = parse_type_str;
diff --git a/qemu/qapi/string-output-visitor.c b/qemu/qapi/string-output-visitor.c
index b86ce2cd0..c2e5c5b92 100644
--- a/qemu/qapi/string-output-visitor.c
+++ b/qemu/qapi/string-output-visitor.c
@@ -1,7 +1,7 @@
/*
* String printing Visitor
*
- * Copyright Red Hat, Inc. 2012
+ * Copyright Red Hat, Inc. 2012-2016
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
*
@@ -10,6 +10,7 @@
*
*/
+#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qapi/string-output-visitor.h"
#include "qapi/visitor-impl.h"
@@ -66,6 +67,11 @@ struct StringOutputVisitor
GList *ranges;
};
+static StringOutputVisitor *to_sov(Visitor *v)
+{
+ return container_of(v, StringOutputVisitor, visitor);
+}
+
static void string_output_set(StringOutputVisitor *sov, char *string)
{
if (sov->string) {
@@ -116,10 +122,10 @@ static void format_string(StringOutputVisitor *sov, Range *r, bool next,
}
}
-static void print_type_int(Visitor *v, int64_t *obj, const char *name,
- Error **errp)
+static void print_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
GList *l;
switch (sov->list_mode) {
@@ -192,10 +198,18 @@ static void print_type_int(Visitor *v, int64_t *obj, const char *name,
}
}
-static void print_type_size(Visitor *v, uint64_t *obj, const char *name,
- Error **errp)
+static void print_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ /* FIXME: print_type_int64 mishandles values over INT64_MAX */
+ int64_t i = *obj;
+ print_type_int64(v, name, &i, errp);
+}
+
+static void print_type_size(Visitor *v, const char *name, uint64_t *obj,
+ Error **errp)
+{
+ StringOutputVisitor *sov = to_sov(v);
static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E' };
uint64_t div, val;
char *out;
@@ -223,17 +237,17 @@ static void print_type_size(Visitor *v, uint64_t *obj, const char *name,
string_output_set(sov, out);
}
-static void print_type_bool(Visitor *v, bool *obj, const char *name,
+static void print_type_bool(Visitor *v, const char *name, bool *obj,
Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
string_output_set(sov, g_strdup(*obj ? "true" : "false"));
}
-static void print_type_str(Visitor *v, char **obj, const char *name,
+static void print_type_str(Visitor *v, const char *name, char **obj,
Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
char *out;
if (sov->human) {
@@ -244,17 +258,17 @@ static void print_type_str(Visitor *v, char **obj, const char *name,
string_output_set(sov, out);
}
-static void print_type_number(Visitor *v, double *obj, const char *name,
+static void print_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
string_output_set(sov, g_strdup_printf("%f", *obj));
}
static void
start_list(Visitor *v, const char *name, Error **errp)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
/* we can't traverse a list in a list */
assert(sov->list_mode == LM_NONE);
@@ -262,10 +276,9 @@ start_list(Visitor *v, const char *name, Error **errp)
sov->head = true;
}
-static GenericList *
-next_list(Visitor *v, GenericList **list, Error **errp)
+static GenericList *next_list(Visitor *v, GenericList **list, size_t size)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
GenericList *ret = NULL;
if (*list) {
if (sov->head) {
@@ -289,10 +302,9 @@ next_list(Visitor *v, GenericList **list, Error **errp)
return ret;
}
-static void
-end_list(Visitor *v, Error **errp)
+static void end_list(Visitor *v)
{
- StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ StringOutputVisitor *sov = to_sov(v);
assert(sov->list_mode == LM_STARTED ||
sov->list_mode == LM_END ||
@@ -340,7 +352,8 @@ StringOutputVisitor *string_output_visitor_new(bool human)
v->string = g_string_new(NULL);
v->human = human;
v->visitor.type_enum = output_type_enum;
- v->visitor.type_int = print_type_int;
+ v->visitor.type_int64 = print_type_int64;
+ v->visitor.type_uint64 = print_type_uint64;
v->visitor.type_size = print_type_size;
v->visitor.type_bool = print_type_bool;
v->visitor.type_str = print_type_str;