summaryrefslogtreecommitdiffstats
path: root/qapi
diff options
context:
space:
mode:
Diffstat (limited to 'qapi')
-rw-r--r--qapi/block-core.json82
-rw-r--r--qapi/block.json30
-rw-r--r--qapi/char.json150
-rw-r--r--qapi/common.json42
-rw-r--r--qapi/crypto.json6
-rw-r--r--qapi/migration.json15
-rw-r--r--qapi/misc.json87
-rw-r--r--qapi/net.json3
-rw-r--r--qapi/qapi-schema.json1
-rw-r--r--qapi/qobject-input-visitor.c9
-rw-r--r--qapi/rdma.json38
-rw-r--r--qapi/run-state.json44
-rw-r--r--qapi/string-input-visitor.c413
-rw-r--r--qapi/tpm.json5
-rw-r--r--qapi/transaction.json12
-rw-r--r--qapi/ui.json3
16 files changed, 564 insertions, 376 deletions
diff --git a/qapi/block-core.json b/qapi/block-core.json
index d4fe710836..91685be6c2 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1143,8 +1143,10 @@
# This command is now obsolete and will always return an error since 2.10
#
##
-{ 'command': 'block_passwd', 'data': {'*device': 'str',
- '*node-name': 'str', 'password': 'str'} }
+{ 'command': 'block_passwd',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'password': 'str' } }
##
# @block_resize:
@@ -1171,9 +1173,10 @@
# <- { "return": {} }
#
##
-{ 'command': 'block_resize', 'data': { '*device': 'str',
- '*node-name': 'str',
- 'size': 'int' }}
+{ 'command': 'block_resize',
+ 'data': { '*device': 'str',
+ '*node-name': 'str',
+ 'size': 'int' } }
##
# @NewImageMode:
@@ -1803,29 +1806,29 @@
# Currently, all dirty tracking bitmaps are loaded from Qcow2 on
# open.
#
-# @x-disabled: the bitmap is created in the disabled state, which means that
-# it will not track drive changes. The bitmap may be enabled with
-# x-block-dirty-bitmap-enable. Default is false. (Since: 3.0)
+# @disabled: the bitmap is created in the disabled state, which means that
+# it will not track drive changes. The bitmap may be enabled with
+# block-dirty-bitmap-enable. Default is false. (Since: 4.0)
#
# Since: 2.4
##
{ 'struct': 'BlockDirtyBitmapAdd',
'data': { 'node': 'str', 'name': 'str', '*granularity': 'uint32',
- '*persistent': 'bool', '*autoload': 'bool', '*x-disabled': 'bool' } }
+ '*persistent': 'bool', '*autoload': 'bool', '*disabled': 'bool' } }
##
# @BlockDirtyBitmapMerge:
#
# @node: name of device/node which the bitmap is tracking
#
-# @dst_name: name of the destination dirty bitmap
+# @target: name of the destination dirty bitmap
#
-# @src_name: name of the source dirty bitmap
+# @bitmaps: name(s) of the source dirty bitmap(s)
#
-# Since: 3.0
+# Since: 4.0
##
{ 'struct': 'BlockDirtyBitmapMerge',
- 'data': { 'node': 'str', 'dst_name': 'str', 'src_name': 'str' } }
+ 'data': { 'node': 'str', 'target': 'str', 'bitmaps': ['str'] } }
##
# @block-dirty-bitmap-add:
@@ -1896,7 +1899,7 @@
'data': 'BlockDirtyBitmap' }
##
-# @x-block-dirty-bitmap-enable:
+# @block-dirty-bitmap-enable:
#
# Enables a dirty bitmap so that it will begin tracking disk changes.
#
@@ -1904,20 +1907,20 @@
# If @node is not a valid block device, DeviceNotFound
# If @name is not found, GenericError with an explanation
#
-# Since: 3.0
+# Since: 4.0
#
# Example:
#
-# -> { "execute": "x-block-dirty-bitmap-enable",
+# -> { "execute": "block-dirty-bitmap-enable",
# "arguments": { "node": "drive0", "name": "bitmap0" } }
# <- { "return": {} }
#
##
- { 'command': 'x-block-dirty-bitmap-enable',
+ { 'command': 'block-dirty-bitmap-enable',
'data': 'BlockDirtyBitmap' }
##
-# @x-block-dirty-bitmap-disable:
+# @block-dirty-bitmap-disable:
#
# Disables a dirty bitmap so that it will stop tracking disk changes.
#
@@ -1925,42 +1928,42 @@
# If @node is not a valid block device, DeviceNotFound
# If @name is not found, GenericError with an explanation
#
-# Since: 3.0
+# Since: 4.0
#
# Example:
#
-# -> { "execute": "x-block-dirty-bitmap-disable",
+# -> { "execute": "block-dirty-bitmap-disable",
# "arguments": { "node": "drive0", "name": "bitmap0" } }
# <- { "return": {} }
#
##
- { 'command': 'x-block-dirty-bitmap-disable',
+ { 'command': 'block-dirty-bitmap-disable',
'data': 'BlockDirtyBitmap' }
##
-# @x-block-dirty-bitmap-merge:
+# @block-dirty-bitmap-merge:
#
-# FIXME: Rename @src_name and @dst_name to src-name and dst-name.
-#
-# Merge @src_name dirty bitmap to @dst_name dirty bitmap. @src_name dirty
-# bitmap is unchanged. On error, @dst_name is unchanged.
+# Merge dirty bitmaps listed in @bitmaps to the @target dirty bitmap.
+# The @bitmaps dirty bitmaps are unchanged.
+# On error, @target is unchanged.
#
# Returns: nothing on success
# If @node is not a valid block device, DeviceNotFound
-# If @dst_name or @src_name is not found, GenericError
-# If bitmaps has different sizes or granularities, GenericError
+# If any bitmap in @bitmaps or @target is not found, GenericError
+# If any of the bitmaps have different sizes or granularities,
+# GenericError
#
-# Since: 3.0
+# Since: 4.0
#
# Example:
#
-# -> { "execute": "x-block-dirty-bitmap-merge",
-# "arguments": { "node": "drive0", "dst_name": "bitmap0",
-# "src_name": "bitmap1" } }
+# -> { "execute": "block-dirty-bitmap-merge",
+# "arguments": { "node": "drive0", "target": "bitmap0",
+# "bitmaps": ["bitmap1"] } }
# <- { "return": {} }
#
##
- { 'command': 'x-block-dirty-bitmap-merge',
+ { 'command': 'block-dirty-bitmap-merge',
'data': 'BlockDirtyBitmapMerge' }
##
@@ -2620,7 +2623,9 @@
'copy-on-read', 'dmg', 'file', 'ftp', 'ftps', 'gluster',
'host_cdrom', 'host_device', 'http', 'https', 'iscsi', 'luks',
'nbd', 'nfs', 'null-aio', 'null-co', 'nvme', 'parallels', 'qcow',
- 'qcow2', 'qed', 'quorum', 'raw', 'rbd', 'replication', 'sheepdog',
+ 'qcow2', 'qed', 'quorum', 'raw', 'rbd',
+ { 'name': 'replication', 'if': 'defined(CONFIG_REPLICATION)' },
+ 'sheepdog',
'ssh', 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
##
@@ -3377,7 +3382,8 @@
#
# Since: 2.9
##
-{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ],
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @BlockdevOptionsReplication:
@@ -3395,7 +3401,8 @@
{ 'struct': 'BlockdevOptionsReplication',
'base': 'BlockdevOptionsGenericFormat',
'data': { 'mode': 'ReplicationMode',
- '*top-id': 'str' } }
+ '*top-id': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @NFSTransport:
@@ -3711,7 +3718,8 @@
'quorum': 'BlockdevOptionsQuorum',
'raw': 'BlockdevOptionsRaw',
'rbd': 'BlockdevOptionsRbd',
- 'replication':'BlockdevOptionsReplication',
+ 'replication': { 'type': 'BlockdevOptionsReplication',
+ 'if': 'defined(CONFIG_REPLICATION)' },
'sheepdog': 'BlockdevOptionsSheepdog',
'ssh': 'BlockdevOptionsSsh',
'throttle': 'BlockdevOptionsThrottle',
diff --git a/qapi/block.json b/qapi/block.json
index 11f01f28ef..5a79d639e8 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -246,6 +246,10 @@
#
# @writable: Whether clients should be able to write to the device via the
# NBD connection (default false).
+
+# @bitmap: Also export the dirty bitmap reachable from @device, so the
+# NBD client can use NBD_OPT_SET_META_CONTEXT with
+# "qemu:dirty-bitmap:NAME" to inspect the bitmap. (since 4.0)
#
# Returns: error if the server is not running, or export with the same name
# already exists.
@@ -253,7 +257,8 @@
# Since: 1.3.0
##
{ 'command': 'nbd-server-add',
- 'data': {'device': 'str', '*name': 'str', '*writable': 'bool'} }
+ 'data': {'device': 'str', '*name': 'str', '*writable': 'bool',
+ '*bitmap': 'str' } }
##
# @NbdServerRemoveMode:
@@ -297,29 +302,6 @@
'data': {'name': 'str', '*mode': 'NbdServerRemoveMode'} }
##
-# @x-nbd-server-add-bitmap:
-#
-# Expose a dirty bitmap associated with the selected export. The bitmap search
-# starts at the device attached to the export, and includes all backing files.
-# The exported bitmap is then locked until the NBD export is removed.
-#
-# @name: Export name.
-#
-# @bitmap: Bitmap name to search for.
-#
-# @bitmap-export-name: How the bitmap will be seen by nbd clients
-# (default @bitmap)
-#
-# Note: the client must use NBD_OPT_SET_META_CONTEXT with a query of
-# "qemu:dirty-bitmap:NAME" (where NAME matches @bitmap-export-name) to access
-# the exposed bitmap.
-#
-# Since: 3.0
-##
- { 'command': 'x-nbd-server-add-bitmap',
- 'data': {'name': 'str', 'bitmap': 'str', '*bitmap-export-name': 'str'} }
-
-##
# @nbd-server-stop:
#
# Stop QEMU's embedded NBD server, and unregister all devices previously
diff --git a/qapi/char.json b/qapi/char.json
index 79bac598a0..77ed847972 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -25,9 +25,10 @@
#
# Since: 0.14.0
##
-{ 'struct': 'ChardevInfo', 'data': {'label': 'str',
- 'filename': 'str',
- 'frontend-open': 'bool'} }
+{ 'struct': 'ChardevInfo',
+ 'data': { 'label': 'str',
+ 'filename': 'str',
+ 'frontend-open': 'bool' } }
##
# @query-chardev:
@@ -152,7 +153,8 @@
#
##
{ 'command': 'ringbuf-write',
- 'data': {'device': 'str', 'data': 'str',
+ 'data': { 'device': 'str',
+ 'data': 'str',
'*format': 'DataFormat'} }
##
@@ -202,8 +204,9 @@
#
# Since: 2.6
##
-{ 'struct': 'ChardevCommon', 'data': { '*logfile': 'str',
- '*logappend': 'bool' } }
+{ 'struct': 'ChardevCommon',
+ 'data': { '*logfile': 'str',
+ '*logappend': 'bool' } }
##
# @ChardevFile:
@@ -217,9 +220,10 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevFile', 'data': { '*in' : 'str',
- 'out' : 'str',
- '*append': 'bool' },
+{ 'struct': 'ChardevFile',
+ 'data': { '*in': 'str',
+ 'out': 'str',
+ '*append': 'bool' },
'base': 'ChardevCommon' }
##
@@ -232,7 +236,8 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevHostdev', 'data': { 'device' : 'str' },
+{ 'struct': 'ChardevHostdev',
+ 'data': { 'device': 'str' },
'base': 'ChardevCommon' }
##
@@ -260,15 +265,16 @@
#
# Since: 1.4
##
-{ 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
- '*tls-creds' : 'str',
- '*server' : 'bool',
- '*wait' : 'bool',
- '*nodelay' : 'bool',
- '*telnet' : 'bool',
- '*tn3270' : 'bool',
- '*websocket' : 'bool',
- '*reconnect' : 'int' },
+{ 'struct': 'ChardevSocket',
+ 'data': { 'addr': 'SocketAddressLegacy',
+ '*tls-creds': 'str',
+ '*server': 'bool',
+ '*wait': 'bool',
+ '*nodelay': 'bool',
+ '*telnet': 'bool',
+ '*tn3270': 'bool',
+ '*websocket': 'bool',
+ '*reconnect': 'int' },
'base': 'ChardevCommon' }
##
@@ -281,8 +287,9 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevUdp', 'data': { 'remote' : 'SocketAddressLegacy',
- '*local' : 'SocketAddressLegacy' },
+{ 'struct': 'ChardevUdp',
+ 'data': { 'remote': 'SocketAddressLegacy',
+ '*local': 'SocketAddressLegacy' },
'base': 'ChardevCommon' }
##
@@ -294,7 +301,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevMux', 'data': { 'chardev' : 'str' },
+{ 'struct': 'ChardevMux',
+ 'data': { 'chardev': 'str' },
'base': 'ChardevCommon' }
##
@@ -308,7 +316,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevStdio', 'data': { '*signal' : 'bool' },
+{ 'struct': 'ChardevStdio',
+ 'data': { '*signal': 'bool' },
'base': 'ChardevCommon' }
@@ -321,9 +330,10 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpiceChannel', 'data': { 'type' : 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+{ 'struct': 'ChardevSpiceChannel',
+ 'data': { 'type': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevSpicePort:
@@ -334,9 +344,10 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' },
- 'base': 'ChardevCommon' }
-# TODO: 'if': 'defined(CONFIG_SPICE)'
+{ 'struct': 'ChardevSpicePort',
+ 'data': { 'fqdn': 'str' },
+ 'base': 'ChardevCommon',
+ 'if': 'defined(CONFIG_SPICE)' }
##
# @ChardevVC:
@@ -350,10 +361,11 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevVC', 'data': { '*width' : 'int',
- '*height' : 'int',
- '*cols' : 'int',
- '*rows' : 'int' },
+{ 'struct': 'ChardevVC',
+ 'data': { '*width': 'int',
+ '*height': 'int',
+ '*cols': 'int',
+ '*rows': 'int' },
'base': 'ChardevCommon' }
##
@@ -365,7 +377,8 @@
#
# Since: 1.5
##
-{ 'struct': 'ChardevRingbuf', 'data': { '*size' : 'int' },
+{ 'struct': 'ChardevRingbuf',
+ 'data': { '*size': 'int' },
'base': 'ChardevCommon' }
##
@@ -375,29 +388,30 @@
#
# Since: 1.4 (testdev since 2.2, wctablet since 2.9)
##
-{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
- 'serial' : 'ChardevHostdev',
- 'parallel': 'ChardevHostdev',
- 'pipe' : 'ChardevHostdev',
- 'socket' : 'ChardevSocket',
- 'udp' : 'ChardevUdp',
- 'pty' : 'ChardevCommon',
- 'null' : 'ChardevCommon',
- 'mux' : 'ChardevMux',
- 'msmouse': 'ChardevCommon',
- 'wctablet' : 'ChardevCommon',
- 'braille': 'ChardevCommon',
- 'testdev': 'ChardevCommon',
- 'stdio' : 'ChardevStdio',
- 'console': 'ChardevCommon',
- 'spicevmc': 'ChardevSpiceChannel',
-# TODO: { 'type': 'ChardevSpiceChannel', 'if': 'defined(CONFIG_SPICE)' },
- 'spiceport': 'ChardevSpicePort',
-# TODO: { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' },
- 'vc' : 'ChardevVC',
- 'ringbuf': 'ChardevRingbuf',
- # next one is just for compatibility
- 'memory' : 'ChardevRingbuf' } }
+{ 'union': 'ChardevBackend',
+ 'data': { 'file': 'ChardevFile',
+ 'serial': 'ChardevHostdev',
+ 'parallel': 'ChardevHostdev',
+ 'pipe': 'ChardevHostdev',
+ 'socket': 'ChardevSocket',
+ 'udp': 'ChardevUdp',
+ 'pty': 'ChardevCommon',
+ 'null': 'ChardevCommon',
+ 'mux': 'ChardevMux',
+ 'msmouse': 'ChardevCommon',
+ 'wctablet': 'ChardevCommon',
+ 'braille': 'ChardevCommon',
+ 'testdev': 'ChardevCommon',
+ 'stdio': 'ChardevStdio',
+ 'console': 'ChardevCommon',
+ 'spicevmc': { 'type': 'ChardevSpiceChannel',
+ 'if': 'defined(CONFIG_SPICE)' },
+ 'spiceport': { 'type': 'ChardevSpicePort',
+ 'if': 'defined(CONFIG_SPICE)' },
+ 'vc': 'ChardevVC',
+ 'ringbuf': 'ChardevRingbuf',
+ # next one is just for compatibility
+ 'memory': 'ChardevRingbuf' } }
##
# @ChardevReturn:
@@ -409,7 +423,8 @@
#
# Since: 1.4
##
-{ 'struct' : 'ChardevReturn', 'data': { '*pty' : 'str' } }
+{ 'struct' : 'ChardevReturn',
+ 'data': { '*pty': 'str' } }
##
# @chardev-add:
@@ -442,8 +457,9 @@
# <- { "return": { "pty" : "/dev/pty/42" } }
#
##
-{ 'command': 'chardev-add', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-add',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -482,8 +498,9 @@
# <- {"return": {}}
#
##
-{ 'command': 'chardev-change', 'data': {'id' : 'str',
- 'backend' : 'ChardevBackend' },
+{ 'command': 'chardev-change',
+ 'data': { 'id': 'str',
+ 'backend': 'ChardevBackend' },
'returns': 'ChardevReturn' }
##
@@ -503,7 +520,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-remove', 'data': {'id': 'str'} }
+{ 'command': 'chardev-remove',
+ 'data': { 'id': 'str' } }
##
# @chardev-send-break:
@@ -522,7 +540,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'chardev-send-break', 'data': {'id': 'str'} }
+{ 'command': 'chardev-send-break',
+ 'data': { 'id': 'str' } }
##
# @VSERPORT_CHANGE:
@@ -543,4 +562,5 @@
#
##
{ 'event': 'VSERPORT_CHANGE',
- 'data': { 'id': 'str', 'open': 'bool' } }
+ 'data': { 'id': 'str',
+ 'open': 'bool' } }
diff --git a/qapi/common.json b/qapi/common.json
index 021174f04e..99d313ef3b 100644
--- a/qapi/common.json
+++ b/qapi/common.json
@@ -128,6 +128,48 @@
'data': [ 'off', 'auto', 'bar0', 'bar1', 'bar2', 'bar3', 'bar4', 'bar5' ] }
##
+# @PCIELinkSpeed:
+#
+# An enumeration of PCIe link speeds in units of GT/s
+#
+# @2_5: 2.5GT/s
+#
+# @5: 5.0GT/s
+#
+# @8: 8.0GT/s
+#
+# @16: 16.0GT/s
+#
+# Since: 4.0
+##
+{ 'enum': 'PCIELinkSpeed',
+ 'data': [ '2_5', '5', '8', '16' ] }
+
+##
+# @PCIELinkWidth:
+#
+# An enumeration of PCIe link width
+#
+# @1: x1
+#
+# @2: x2
+#
+# @4: x4
+#
+# @8: x8
+#
+# @12: x12
+#
+# @16: x16
+#
+# @32: x32
+#
+# Since: 4.0
+##
+{ 'enum': 'PCIELinkWidth',
+ 'data': [ '1', '2', '4', '8', '12', '16', '32' ] }
+
+##
# @SysEmuTarget:
#
# The comprehensive enumeration of QEMU system emulation ("softmmu")
diff --git a/qapi/crypto.json b/qapi/crypto.json
index a51b434412..b2a4cff683 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -181,11 +181,11 @@
# The options that apply to LUKS encryption format initialization
#
# @cipher-alg: the cipher algorithm for data encryption
-# Currently defaults to 'aes'.
+# Currently defaults to 'aes-256'.
# @cipher-mode: the cipher mode for data encryption
-# Currently defaults to 'cbc'
+# Currently defaults to 'xts'
# @ivgen-alg: the initialization vector generator
-# Currently defaults to 'essiv'
+# Currently defaults to 'plain64'
# @ivgen-hash-alg: the initialization vector generator hash
# Currently defaults to 'sha256'
# @hash-alg: the master key hash algorithm
diff --git a/qapi/migration.json b/qapi/migration.json
index 38d4c41d88..31b589ec26 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1257,7 +1257,8 @@
# Since: 2.9
##
{ 'command': 'xen-set-replication',
- 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' } }
+ 'data': { 'enable': 'bool', 'primary': 'bool', '*failover' : 'bool' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @ReplicationStatus:
@@ -1272,7 +1273,8 @@
# Since: 2.9
##
{ 'struct': 'ReplicationStatus',
- 'data': { 'error': 'bool', '*desc': 'str' } }
+ 'data': { 'error': 'bool', '*desc': 'str' },
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @query-xen-replication-status:
@@ -1289,7 +1291,8 @@
# Since: 2.9
##
{ 'command': 'query-xen-replication-status',
- 'returns': 'ReplicationStatus' }
+ 'returns': 'ReplicationStatus',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @xen-colo-do-checkpoint:
@@ -1305,7 +1308,8 @@
#
# Since: 2.9
##
-{ 'command': 'xen-colo-do-checkpoint' }
+{ 'command': 'xen-colo-do-checkpoint',
+ 'if': 'defined(CONFIG_REPLICATION)' }
##
# @COLOStatus:
@@ -1356,7 +1360,8 @@
#
# Since: 3.0
##
-{ 'command': 'migrate-recover', 'data': { 'uri': 'str' },
+{ 'command': 'migrate-recover',
+ 'data': { 'uri': 'str' },
'allow-oob': true }
##
diff --git a/qapi/misc.json b/qapi/misc.json
index 6c1c5c0a37..24d20a880a 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -1109,7 +1109,7 @@
##
# @cpu-add:
#
-# Adds CPU with specified ID
+# Adds CPU with specified ID.
#
# @id: ID of CPU to be created, valid values [0..max_cpus)
#
@@ -1117,6 +1117,10 @@
#
# Since: 1.5
#
+# Note: This command is deprecated. The `device_add` command should be
+# used instead. See the `query-hotpluggable-cpus` command for
+# details.
+#
# Example:
#
# -> { "execute": "cpu-add", "arguments": { "id": 2 } }
@@ -1235,12 +1239,18 @@
##
# @system_wakeup:
#
-# Wakeup guest from suspend. Does nothing in case the guest isn't suspended.
+# Wake up guest from suspend. If the guest has wake-up from suspend
+# support enabled (wakeup-suspend-support flag from
+# query-current-machine), wake-up guest from suspend if the guest is
+# in SUSPENDED state. Return an error otherwise.
#
# Since: 1.1
#
# Returns: nothing.
#
+# Note: prior to 4.0, this command does nothing in case the guest
+# isn't suspended.
+#
# Example:
#
# -> { "execute": "system_wakeup" }
@@ -2009,6 +2019,30 @@
{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
##
+# @CurrentMachineParams:
+#
+# Information describing the running machine parameters.
+#
+# @wakeup-suspend-support: true if the machine supports wake up from
+# suspend
+#
+# Since: 4.0
+##
+{ 'struct': 'CurrentMachineParams',
+ 'data': { 'wakeup-suspend-support': 'bool'} }
+
+##
+# @query-current-machine:
+#
+# Return information on the current virtual machine.
+#
+# Returns: CurrentMachineParams
+#
+# Since: 4.0
+##
+{ 'command': 'query-current-machine', 'returns': 'CurrentMachineParams' }
+
+##
# @CpuDefinitionInfo:
#
# Virtual CPU definition.
@@ -2381,7 +2415,9 @@
# <- { "return": { "fdset-id": 1, "fd": 3 } }
#
##
-{ 'command': 'add-fd', 'data': {'*fdset-id': 'int', '*opaque': 'str'},
+{ 'command': 'add-fd',
+ 'data': { '*fdset-id': 'int',
+ '*opaque': 'str' },
'returns': 'AddfdInfo' }
##
@@ -2653,7 +2689,8 @@
# }
#
##
-{'command': 'query-command-line-options', 'data': { '*option': 'str' },
+{'command': 'query-command-line-options',
+ 'data': { '*option': 'str' },
'returns': ['CommandLineOptionInfo'],
'allow-preconfig': true }
@@ -3219,6 +3256,8 @@
##
# @query-hotpluggable-cpus:
#
+# TODO: Better documentation; currently there is none.
+#
# Returns: a list of HotpluggableCPU objects.
#
# Since: 2.7
@@ -3439,46 +3478,6 @@
{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability' }
##
-# @CommandDropReason:
-#
-# Reasons that caused one command to be dropped.
-#
-# @queue-full: the command queue is full. This can only occur when
-# the client sends a new non-oob command before the
-# response to the previous non-oob command has been
-# received.
-#
-# Since: 2.12
-##
-{ 'enum': 'CommandDropReason',
- 'data': [ 'queue-full' ] }
-
-##
-# @COMMAND_DROPPED:
-#
-# Emitted when a command is dropped due to some reason. Commands can
-# only be dropped when the oob capability is enabled.
-#
-# @id: The dropped command's "id" field.
-# FIXME Broken by design. Events are broadcast to all monitors. If
-# another monitor's client has a command with the same ID in flight,
-# the event will incorrectly claim that command was dropped.
-#
-# @reason: The reason why the command is dropped.
-#
-# Since: 2.12
-#
-# Example:
-#
-# { "event": "COMMAND_DROPPED",
-# "data": {"result": {"id": "libvirt-102",
-# "reason": "queue-full" } } }
-#
-##
-{ 'event': 'COMMAND_DROPPED' ,
- 'data': { 'id': 'any', 'reason': 'CommandDropReason' } }
-
-##
# @set-numa-node:
#
# Runtime equivalent of '-numa' CLI option, available at
diff --git a/qapi/net.json b/qapi/net.json
index 8f99fd911d..a1a0f39f74 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -657,7 +657,8 @@
# }
#
##
-{ 'command': 'query-rx-filter', 'data': { '*name': 'str' },
+{ 'command': 'query-rx-filter',
+ 'data': { '*name': 'str' },
'returns': ['RxFilterInfo'] }
##
diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json
index 65b6dc2f6f..3bbdfcee84 100644
--- a/qapi/qapi-schema.json
+++ b/qapi/qapi-schema.json
@@ -86,6 +86,7 @@
{ 'include': 'char.json' }
{ 'include': 'job.json' }
{ 'include': 'net.json' }
+{ 'include': 'rdma.json' }
{ 'include': 'rocker.json' }
{ 'include': 'tpm.json' }
{ 'include': 'ui.json' }
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 3e88b27f9e..07465f9947 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -562,19 +562,20 @@ static void qobject_input_type_number_keyval(Visitor *v, const char *name,
{
QObjectInputVisitor *qiv = to_qiv(v);
const char *str = qobject_input_get_keyval(qiv, name, errp);
- char *endp;
+ double val;
if (!str) {
return;
}
- errno = 0;
- *obj = strtod(str, &endp);
- if (errno || endp == str || *endp || !isfinite(*obj)) {
+ if (qemu_strtod_finite(str, NULL, &val)) {
/* TODO report -ERANGE more nicely */
error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
full_name(qiv, name), "number");
+ return;
}
+
+ *obj = val;
}
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
diff --git a/qapi/rdma.json b/qapi/rdma.json
new file mode 100644
index 0000000000..b58105b1b6
--- /dev/null
+++ b/qapi/rdma.json
@@ -0,0 +1,38 @@
+# -*- Mode: Python -*-
+#
+
+##
+# = RDMA device
+##
+
+##
+# @RDMA_GID_STATUS_CHANGED:
+#
+# Emitted when guest driver adds/deletes GID to/from device
+#
+# @netdev: RoCE Network Device name
+#
+# @gid-status: Add or delete indication
+#
+# @subnet-prefix: Subnet Prefix
+#
+# @interface-id : Interface ID
+#
+# Since: 4.0
+#
+# Example:
+#
+# <- {"timestamp": {"seconds": 1541579657, "microseconds": 986760},
+# "event": "RDMA_GID_STATUS_CHANGED",
+# "data":
+# {"netdev": "bridge0",
+# "interface-id": 15880512517475447892,
+# "gid-status": true,
+# "subnet-prefix": 33022}}
+#
+##
+{ 'event': 'RDMA_GID_STATUS_CHANGED',
+ 'data': { 'netdev' : 'str',
+ 'gid-status' : 'bool',
+ 'subnet-prefix' : 'uint64',
+ 'interface-id' : 'uint64' } }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index 332e44897b..d7477cd715 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -60,6 +60,42 @@
'guest-panicked', 'colo', 'preconfig' ] }
##
+# @ShutdownCause:
+#
+# An enumeration of reasons for a Shutdown.
+#
+# @none: No shutdown request pending
+#
+# @host-error: An error prevents further use of guest
+#
+# @host-qmp-quit: Reaction to the QMP command 'quit'
+#
+# @host-qmp-system-reset: Reaction to the QMP command 'system_reset'
+#
+# @host-signal: Reaction to a signal, such as SIGINT
+#
+# @host-ui: Reaction to a UI event, like window close
+#
+# @guest-shutdown: Guest shutdown/suspend request, via ACPI or other
+# hardware-specific means
+#
+# @guest-reset: Guest reset request, and command line turns that into
+# a shutdown
+#
+# @guest-panic: Guest panicked, and command line turns that into a shutdown
+#
+# @subsystem-reset: Partial guest reset that does not trigger QMP events and
+# ignores --no-reboot. This is useful for sanitizing
+# hypercalls on s390 that are used during kexec/kdump/boot
+#
+##
+{ 'enum': 'ShutdownCause',
+ # Beware, shutdown_caused_by_guest() depends on enumeration order
+ 'data': [ 'none', 'host-error', 'host-qmp-quit', 'host-qmp-system-reset',
+ 'host-signal', 'host-ui', 'guest-shutdown', 'guest-reset',
+ 'guest-panic', 'subsystem-reset'] }
+
+##
# @StatusInfo:
#
# Information about VCPU run state
@@ -107,6 +143,8 @@
# a guest-initiated ACPI shutdown request or other hardware-specific action)
# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
#
+# @reason: The @ShutdownCause which resulted in the SHUTDOWN. (since 4.0)
+#
# Note: If the command-line option "-no-shutdown" has been specified, qemu will
# not exit, and a STOP event will eventually follow the SHUTDOWN event
#
@@ -118,7 +156,7 @@
# "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
#
##
-{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }
+{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } }
##
# @POWERDOWN:
@@ -146,6 +184,8 @@
# rather than a host request (such as the QMP command system_reset).
# (since 2.10)
#
+# @reason: The @ShutdownCause of the RESET. (since 4.0)
+#
# Since: 0.12.0
#
# Example:
@@ -154,7 +194,7 @@
# "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
#
##
-{ 'event': 'RESET', 'data': { 'guest': 'bool' } }
+{ 'event': 'RESET', 'data': { 'guest': 'bool', 'reason': 'ShutdownCause' } }
##
# @STOP:
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index b3fdd0827d..bd92080667 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -4,10 +4,10 @@
* Copyright Red Hat, Inc. 2012-2016
*
* Author: Paolo Bonzini <pbonzini@redhat.com>
+ * David Hildenbrand <david@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
- *
*/
#include "qemu/osdep.h"
@@ -18,20 +18,42 @@
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qnull.h"
#include "qemu/option.h"
-#include "qemu/queue.h"
-#include "qemu/range.h"
-
+#include "qemu/cutils.h"
+
+typedef enum ListMode {
+ /* no list parsing active / no list expected */
+ LM_NONE,
+ /* we have an unparsed string remaining */
+ LM_UNPARSED,
+ /* we have an unfinished int64 range */
+ LM_INT64_RANGE,
+ /* we have an unfinished uint64 range */
+ LM_UINT64_RANGE,
+ /* we have parsed the string completely and no range is remaining */
+ LM_END,
+} ListMode;
+
+/* protect against DOS attacks, limit the amount of elements per range */
+#define RANGE_MAX_ELEMENTS 65536
+
+typedef union RangeElement {
+ int64_t i64;
+ uint64_t u64;
+} RangeElement;
struct StringInputVisitor
{
Visitor visitor;
- GList *ranges;
- GList *cur_range;
- int64_t cur;
+ /* List parsing state */
+ ListMode lm;
+ RangeElement rangeNext;
+ RangeElement rangeEnd;
+ const char *unparsed_string;
+ void *list;
+ /* The original string to parse */
const char *string;
- void *list; /* Only needed for sanity checking the caller */
};
static StringInputVisitor *to_siv(Visitor *v)
@@ -39,136 +61,42 @@ static StringInputVisitor *to_siv(Visitor *v)
return container_of(v, StringInputVisitor, visitor);
}
-static void free_range(void *range, void *dummy)
-{
- g_free(range);
-}
-
-static int parse_str(StringInputVisitor *siv, const char *name, Error **errp)
-{
- char *str = (char *) siv->string;
- long long start, end;
- Range *cur;
- char *endptr;
-
- if (siv->ranges) {
- return 0;
- }
-
- if (!*str) {
- return 0;
- }
-
- do {
- errno = 0;
- start = strtoll(str, &endptr, 0);
- if (errno == 0 && endptr > str) {
- if (*endptr == '\0') {
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, start);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- str = NULL;
- } else if (*endptr == '-') {
- str = endptr + 1;
- errno = 0;
- end = strtoll(str, &endptr, 0);
- if (errno == 0 && endptr > str && start <= end &&
- (start > INT64_MAX - 65536 ||
- end < start + 65536)) {
- if (*endptr == '\0') {
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, end);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- str = NULL;
- } else if (*endptr == ',') {
- str = endptr + 1;
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, end);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- } else {
- goto error;
- }
- } else {
- goto error;
- }
- } else if (*endptr == ',') {
- str = endptr + 1;
- cur = g_malloc0(sizeof(*cur));
- range_set_bounds(cur, start, start);
- siv->ranges = range_list_insert(siv->ranges, cur);
- cur = NULL;
- } else {
- goto error;
- }
- } else {
- goto error;
- }
- } while (str);
-
- return 0;
-error:
- g_list_foreach(siv->ranges, free_range, NULL);
- g_list_free(siv->ranges);
- siv->ranges = NULL;
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
- "an int64 value or range");
- return -1;
-}
-
-static void
-start_list(Visitor *v, const char *name, GenericList **list, size_t size,
- Error **errp)
+static void start_list(Visitor *v, const char *name, GenericList **list,
+ size_t size, Error **errp)
{
StringInputVisitor *siv = to_siv(v);
- /* We don't support visits without a list */
- assert(list);
+ assert(siv->lm == LM_NONE);
siv->list = list;
+ siv->unparsed_string = siv->string;
- if (parse_str(siv, name, errp) < 0) {
- *list = NULL;
- return;
- }
-
- siv->cur_range = g_list_first(siv->ranges);
- if (siv->cur_range) {
- Range *r = siv->cur_range->data;
- if (r) {
- siv->cur = range_lob(r);
+ if (!siv->string[0]) {
+ if (list) {
+ *list = NULL;
}
- *list = g_malloc0(size);
+ siv->lm = LM_END;
} else {
- *list = NULL;
+ if (list) {
+ *list = g_malloc0(size);
+ }
+ siv->lm = LM_UNPARSED;
}
}
static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
{
StringInputVisitor *siv = to_siv(v);
- Range *r;
- if (!siv->ranges || !siv->cur_range) {
+ switch (siv->lm) {
+ case LM_END:
return NULL;
- }
-
- r = siv->cur_range->data;
- if (!r) {
- return NULL;
- }
-
- if (!range_contains(r, siv->cur)) {
- siv->cur_range = g_list_next(siv->cur_range);
- if (!siv->cur_range) {
- return NULL;
- }
- r = siv->cur_range->data;
- if (!r) {
- return NULL;
- }
- siv->cur = range_lob(r);
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ /* we have an unparsed string or something left in a range */
+ break;
+ default:
+ abort();
}
tail->next = g_malloc0(size);
@@ -178,88 +106,208 @@ static GenericList *next_list(Visitor *v, GenericList *tail, size_t size)
static void check_list(Visitor *v, Error **errp)
{
const StringInputVisitor *siv = to_siv(v);
- Range *r;
- GList *cur_range;
- if (!siv->ranges || !siv->cur_range) {
+ switch (siv->lm) {
+ case LM_INT64_RANGE:
+ case LM_UINT64_RANGE:
+ case LM_UNPARSED:
+ error_setg(errp, "Fewer list elements expected");
return;
- }
-
- r = siv->cur_range->data;
- if (!r) {
+ case LM_END:
return;
+ default:
+ abort();
}
-
- if (!range_contains(r, siv->cur)) {
- cur_range = g_list_next(siv->cur_range);
- if (!cur_range) {
- return;
- }
- r = cur_range->data;
- if (!r) {
- return;
- }
- }
-
- error_setg(errp, "Range contains too many values");
}
static void end_list(Visitor *v, void **obj)
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm != LM_NONE);
assert(siv->list == obj);
+ siv->list = NULL;
+ siv->unparsed_string = NULL;
+ siv->lm = LM_NONE;
+}
+
+static int try_parse_int64_list_entry(StringInputVisitor *siv, int64_t *obj)
+{
+ const char *endptr;
+ int64_t start, end;
+
+ /* parse a simple int64 or range */
+ if (qemu_strtoi64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtoi64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
+ }
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
+ }
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_INT64_RANGE;
+ siv->rangeNext.i64 = start;
+ siv->rangeEnd.i64 = end;
+ return 0;
}
static void parse_type_int64(Visitor *v, const char *name, int64_t *obj,
Error **errp)
{
StringInputVisitor *siv = to_siv(v);
-
- if (parse_str(siv, name, errp) < 0) {
+ int64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple int64, bail out if not completely consumed */
+ if (qemu_strtoi64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+ name ? name : "null", "int64");
+ return;
+ }
+ *obj = val;
return;
+ case LM_UNPARSED:
+ if (try_parse_int64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of int64 values or ranges");
+ return;
+ }
+ assert(siv->lm == LM_INT64_RANGE);
+ /* fall through */
+ case LM_INT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.i64 <= siv->rangeEnd.i64);
+ *obj = siv->rangeNext.i64++;
+
+ if (siv->rangeNext.i64 > siv->rangeEnd.i64 || *obj == INT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return;
+ default:
+ abort();
}
+}
- if (!siv->ranges) {
- goto error;
- }
-
- if (!siv->cur_range) {
- Range *r;
+static int try_parse_uint64_list_entry(StringInputVisitor *siv, uint64_t *obj)
+{
+ const char *endptr;
+ uint64_t start, end;
- siv->cur_range = g_list_first(siv->ranges);
- if (!siv->cur_range) {
- goto error;
+ /* parse a simple uint64 or range */
+ if (qemu_strtou64(siv->unparsed_string, &endptr, 0, &start)) {
+ return -EINVAL;
+ }
+ end = start;
+
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ case '-':
+ /* parse the end of the range */
+ if (qemu_strtou64(endptr + 1, &endptr, 0, &end)) {
+ return -EINVAL;
}
-
- r = siv->cur_range->data;
- if (!r) {
- goto error;
+ if (start > end || end - start >= RANGE_MAX_ELEMENTS) {
+ return -EINVAL;
}
-
- siv->cur = range_lob(r);
+ switch (endptr[0]) {
+ case '\0':
+ siv->unparsed_string = endptr;
+ break;
+ case ',':
+ siv->unparsed_string = endptr + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
}
- *obj = siv->cur;
- siv->cur++;
- return;
-
-error:
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
- "an int64 value or range");
+ /* we have a proper range (with maybe only one element) */
+ siv->lm = LM_UINT64_RANGE;
+ siv->rangeNext.u64 = start;
+ siv->rangeEnd.u64 = end;
+ return 0;
}
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;
+ StringInputVisitor *siv = to_siv(v);
+ uint64_t val;
+
+ switch (siv->lm) {
+ case LM_NONE:
+ /* just parse a simple uint64, bail out if not completely consumed */
+ if (qemu_strtou64(siv->string, NULL, 0, &val)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "uint64");
+ return;
+ }
+ *obj = val;
+ return;
+ case LM_UNPARSED:
+ if (try_parse_uint64_list_entry(siv, obj)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
+ "list of uint64 values or ranges");
+ return;
+ }
+ assert(siv->lm == LM_UINT64_RANGE);
+ /* fall through */
+ case LM_UINT64_RANGE:
+ /* return the next element in the range */
+ assert(siv->rangeNext.u64 <= siv->rangeEnd.u64);
+ *obj = siv->rangeNext.u64++;
+
+ if (siv->rangeNext.u64 > siv->rangeEnd.u64 || *obj == UINT64_MAX) {
+ /* end of range, check if there is more to parse */
+ siv->lm = siv->unparsed_string[0] ? LM_UNPARSED : LM_END;
+ }
+ return;
+ case LM_END:
+ error_setg(errp, "Fewer list elements expected");
+ return;
+ default:
+ abort();
}
}
@@ -270,6 +318,7 @@ static void parse_type_size(Visitor *v, const char *name, uint64_t *obj,
Error *err = NULL;
uint64_t val;
+ assert(siv->lm == LM_NONE);
parse_option_size(name, siv->string, &val, &err);
if (err) {
error_propagate(errp, err);
@@ -284,6 +333,7 @@ static void parse_type_bool(Visitor *v, const char *name, bool *obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
if (!strcasecmp(siv->string, "on") ||
!strcasecmp(siv->string, "yes") ||
!strcasecmp(siv->string, "true")) {
@@ -306,6 +356,7 @@ static void parse_type_str(Visitor *v, const char *name, char **obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
*obj = g_strdup(siv->string);
}
@@ -313,12 +364,10 @@ static void parse_type_number(Visitor *v, const char *name, double *obj,
Error **errp)
{
StringInputVisitor *siv = to_siv(v);
- char *endp = (char *) siv->string;
double val;
- errno = 0;
- val = strtod(siv->string, &endp);
- if (errno || endp == siv->string || *endp) {
+ assert(siv->lm == LM_NONE);
+ if (qemu_strtod_finite(siv->string, NULL, &val)) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"number");
return;
@@ -332,9 +381,10 @@ static void parse_type_null(Visitor *v, const char *name, QNull **obj,
{
StringInputVisitor *siv = to_siv(v);
+ assert(siv->lm == LM_NONE);
*obj = NULL;
- if (!siv->string || siv->string[0]) {
+ if (siv->string[0]) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"null");
return;
@@ -347,8 +397,6 @@ static void string_input_free(Visitor *v)
{
StringInputVisitor *siv = to_siv(v);
- g_list_foreach(siv->ranges, free_range, NULL);
- g_list_free(siv->ranges);
g_free(siv);
}
@@ -374,5 +422,6 @@ Visitor *string_input_visitor_new(const char *str)
v->visitor.free = string_input_free;
v->string = str;
+ v->lm = LM_NONE;
return &v->visitor;
}
diff --git a/qapi/tpm.json b/qapi/tpm.json
index d50deef5e9..b30323bb6b 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -76,8 +76,9 @@
#
# Since: 1.5
##
-{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
- '*cancel-path' : 'str'} }
+{ 'struct': 'TPMPassthroughOptions',
+ 'data': { '*path': 'str',
+ '*cancel-path': 'str' } }
##
# @TPMEmulatorOptions:
diff --git a/qapi/transaction.json b/qapi/transaction.json
index 5875cdb16c..95edb78227 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -46,9 +46,9 @@
# - @abort: since 1.6
# - @block-dirty-bitmap-add: since 2.5
# - @block-dirty-bitmap-clear: since 2.5
-# - @x-block-dirty-bitmap-enable: since 3.0
-# - @x-block-dirty-bitmap-disable: since 3.0
-# - @x-block-dirty-bitmap-merge: since 3.1
+# - @block-dirty-bitmap-enable: since 4.0
+# - @block-dirty-bitmap-disable: since 4.0
+# - @block-dirty-bitmap-merge: since 4.0
# - @blockdev-backup: since 2.3
# - @blockdev-snapshot: since 2.5
# - @blockdev-snapshot-internal-sync: since 1.7
@@ -62,9 +62,9 @@
'abort': 'Abort',
'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
'block-dirty-bitmap-clear': 'BlockDirtyBitmap',
- 'x-block-dirty-bitmap-enable': 'BlockDirtyBitmap',
- 'x-block-dirty-bitmap-disable': 'BlockDirtyBitmap',
- 'x-block-dirty-bitmap-merge': 'BlockDirtyBitmapMerge',
+ 'block-dirty-bitmap-enable': 'BlockDirtyBitmap',
+ 'block-dirty-bitmap-disable': 'BlockDirtyBitmap',
+ 'block-dirty-bitmap-merge': 'BlockDirtyBitmapMerge',
'blockdev-backup': 'BlockdevBackup',
'blockdev-snapshot': 'BlockdevSnapshot',
'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal',
diff --git a/qapi/ui.json b/qapi/ui.json
index fd39acb5c3..5ad13248d5 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -598,7 +598,8 @@
# Notes: An empty password in this command will set the password to the empty
# string. Existing clients are unaffected by executing this command.
##
-{ 'command': 'change-vnc-password', 'data': {'password': 'str'},
+{ 'command': 'change-vnc-password',
+ 'data': { 'password': 'str' },
'if': 'defined(CONFIG_VNC)' }
##