<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Oct 25, 2021 at 1:25 AM Markus Armbruster <<a href="mailto:armbru@redhat.com">armbru@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Add special feature 'unstable' everywhere the name starts with 'x-',<br>
except for InputBarrierProperties member x-origin and<br>
MemoryBackendProperties member x-use-canonical-path-for-ramblock-id,<br>
because these two are actually stable.<br>
<br>
Signed-off-by: Markus Armbruster <<a href="mailto:armbru@redhat.com" target="_blank">armbru@redhat.com</a>><br>
---<br>
 qapi/block-core.json | 123 +++++++++++++++++++++++++++++++------------<br>
 qapi/migration.json  |  35 +++++++++---<br>
 qapi/misc.json       |   6 ++-<br>
 qapi/qom.json        |  11 ++--<br>
 4 files changed, 130 insertions(+), 45 deletions(-)<br>
<br>
diff --git a/qapi/block-core.json b/qapi/block-core.json<br>
index 6d3217abb6..ce2c1352cb 100644<br>
--- a/qapi/block-core.json<br>
+++ b/qapi/block-core.json<br>
@@ -1438,6 +1438,9 @@<br>
 #<br>
 # @x-perf: Performance options. (Since 6.0)<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-perf is experimental.<br>
+#<br></blockquote><div><br></div><div>It'd be a lot cooler if we could annotate the unstable member directly instead of confusing it with the syntax that might describe the entire struct/union/command/etc, but ... eh, it's just a doc field, so I'm not gonna press on this. I don't have the energy to get into a doc formatting standard discussion right now, so: sure, why not?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 # Note: @on-source-error and @on-target-error only affect background<br>
 #       I/O.  If an error occurs during a guest write request, the device's<br>
 #       rerror/werror actions will be used.<br>
@@ -1452,7 +1455,9 @@<br>
             '*on-source-error': 'BlockdevOnError',<br>
             '*on-target-error': 'BlockdevOnError',<br>
             '*auto-finalize': 'bool', '*auto-dismiss': 'bool',<br>
-            '*filter-node-name': 'str', '*x-perf': 'BackupPerf'  } }<br>
+            '*filter-node-name': 'str',<br>
+            '*x-perf': { 'type': 'BackupPerf',<br>
+                         'features': [ 'unstable' ] } } }<br>
<br>
 ##<br>
 # @DriveBackup:<br>
@@ -1916,9 +1921,13 @@<br>
 #<br>
 # Get the block graph.<br>
 #<br>
+# Features:<br>
+# @unstable: This command is meant for debugging.<br>
+#<br>
 # Since: 4.0<br>
 ##<br>
-{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph' }<br>
+{ 'command': 'x-debug-query-block-graph', 'returns': 'XDbgBlockGraph',<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @drive-mirror:<br>
@@ -2257,6 +2266,9 @@<br>
 #<br>
 # Get bitmap SHA256.<br>
 #<br>
+# Features:<br>
+# @unstable: This command is meant for debugging.<br>
+#<br>
 # Returns: - BlockDirtyBitmapSha256 on success<br>
 #          - If @node is not a valid block device, DeviceNotFound<br>
 #          - If @name is not found or if hashing has failed, GenericError with an<br>
@@ -2265,7 +2277,8 @@<br>
 # Since: 2.10<br>
 ##<br>
 { 'command': 'x-debug-block-dirty-bitmap-sha256',<br>
-  'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256' }<br>
+  'data': 'BlockDirtyBitmap', 'returns': 'BlockDirtyBitmapSha256',<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @blockdev-mirror:<br>
@@ -2495,27 +2508,57 @@<br>
 #<br>
 # Properties for throttle-group objects.<br>
 #<br>
-# The options starting with x- are aliases for the same key without x- in<br>
-# the @limits object. As indicated by the x- prefix, this is not a stable<br>
-# interface and may be removed or changed incompatibly in the future. Use<br>
-# @limits for a supported stable interface.<br>
-#<br>
 # @limits: limits to apply for this throttle group<br>
 #<br>
+# Features:<br>
+# @unstable: All members starting with x- are aliases for the same key<br>
+#            without x- in the @limits object.  This is not a stable<br>
+#            interface and may be removed or changed incompatibly in<br>
+#            the future.  Use @limits for a supported stable<br>
+#            interface.<br>
+#<br>
 # Since: 2.11<br>
 ##<br>
 { 'struct': 'ThrottleGroupProperties',<br>
   'data': { '*limits': 'ThrottleLimits',<br>
-            '*x-iops-total' : 'int', '*x-iops-total-max' : 'int',<br>
-            '*x-iops-total-max-length' : 'int', '*x-iops-read' : 'int',<br>
-            '*x-iops-read-max' : 'int', '*x-iops-read-max-length' : 'int',<br>
-            '*x-iops-write' : 'int', '*x-iops-write-max' : 'int',<br>
-            '*x-iops-write-max-length' : 'int', '*x-bps-total' : 'int',<br>
-            '*x-bps-total-max' : 'int', '*x-bps-total-max-length' : 'int',<br>
-            '*x-bps-read' : 'int', '*x-bps-read-max' : 'int',<br>
-            '*x-bps-read-max-length' : 'int', '*x-bps-write' : 'int',<br>
-            '*x-bps-write-max' : 'int', '*x-bps-write-max-length' : 'int',<br>
-            '*x-iops-size' : 'int' } }<br>
+            '*x-iops-total': { 'type': 'int',<br>
+                               'features': [ 'unstable' ] },<br>
+            '*x-iops-total-max': { 'type': 'int',<br>
+                                   'features': [ 'unstable' ] },<br>
+            '*x-iops-total-max-length': { 'type': 'int',<br>
+                                          'features': [ 'unstable' ] },<br>
+            '*x-iops-read': { 'type': 'int',<br>
+                              'features': [ 'unstable' ] },<br>
+            '*x-iops-read-max': { 'type': 'int',<br>
+                                  'features': [ 'unstable' ] },<br>
+            '*x-iops-read-max-length': { 'type': 'int',<br>
+                                         'features': [ 'unstable' ] },<br>
+            '*x-iops-write': { 'type': 'int',<br>
+                               'features': [ 'unstable' ] },<br>
+            '*x-iops-write-max': { 'type': 'int',<br>
+                                   'features': [ 'unstable' ] },<br>
+            '*x-iops-write-max-length': { 'type': 'int',<br>
+                                          'features': [ 'unstable' ] },<br>
+            '*x-bps-total': { 'type': 'int',<br>
+                              'features': [ 'unstable' ] },<br>
+            '*x-bps-total-max': { 'type': 'int',<br>
+                                  'features': [ 'unstable' ] },<br>
+            '*x-bps-total-max-length': { 'type': 'int',<br>
+                                         'features': [ 'unstable' ] },<br>
+            '*x-bps-read': { 'type': 'int',<br>
+                             'features': [ 'unstable' ] },<br>
+            '*x-bps-read-max': { 'type': 'int',<br>
+                                 'features': [ 'unstable' ] },<br>
+            '*x-bps-read-max-length': { 'type': 'int',<br>
+                                        'features': [ 'unstable' ] },<br>
+            '*x-bps-write': { 'type': 'int',<br>
+                              'features': [ 'unstable' ] },<br>
+            '*x-bps-write-max': { 'type': 'int',<br>
+                                  'features': [ 'unstable' ] },<br>
+            '*x-bps-write-max-length': { 'type': 'int',<br>
+                                         'features': [ 'unstable' ] },<br>
+            '*x-iops-size': { 'type': 'int',<br>
+                              'features': [ 'unstable' ] } } }<br>
<br>
 ##<br>
 # @block-stream:<br>
@@ -2916,6 +2959,7 @@<br>
 #                          read-only when the last writer is detached. This<br>
 #                          allows giving QEMU write permissions only on demand<br>
 #                          when an operation actually needs write access.<br>
+# @unstable: Member x-check-cache-dropped is meant for debugging.<br>
 #<br>
 # Since: 2.9<br>
 ##<br>
@@ -2926,7 +2970,8 @@<br>
             '*aio': 'BlockdevAioOptions',<br>
             '*drop-cache': {'type': 'bool',<br>
                             'if': 'CONFIG_LINUX'},<br>
-            '*x-check-cache-dropped': 'bool' },<br>
+            '*x-check-cache-dropped': { 'type': 'bool',<br>
+                                        'features': [ 'unstable' ] } },<br>
   'features': [ { 'name': 'dynamic-auto-read-only',<br>
                   'if': 'CONFIG_POSIX' } ] }<br>
<br>
@@ -4041,13 +4086,16 @@<br>
 #                   future requests before a successful reconnect will<br>
 #                   immediately fail. Default 0 (Since 4.2)<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-dirty-bitmap is experimental.<br>
+#<br>
 # Since: 2.9<br>
 ##<br>
 { 'struct': 'BlockdevOptionsNbd',<br>
   'data': { 'server': 'SocketAddress',<br>
             '*export': 'str',<br>
             '*tls-creds': 'str',<br>
-            '*x-dirty-bitmap': 'str',<br>
+            '*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] },<br>
             '*reconnect-delay': 'uint32' } }<br>
<br>
 ##<br>
@@ -4865,13 +4913,17 @@<br>
 #                   and replacement of an active keyslot<br>
 #                   (possible loss of data if IO error happens)<br>
 #<br>
+# Features:<br>
+# @unstable: This command is experimental.<br>
+#<br>
 # Since: 5.1<br>
 ##<br>
 { 'command': 'x-blockdev-amend',<br>
   'data': { 'job-id': 'str',<br>
             'node-name': 'str',<br>
             'options': 'BlockdevAmendOptions',<br>
-            '*force': 'bool' } }<br>
+            '*force': 'bool' },<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @BlockErrorAction:<br>
@@ -5242,16 +5294,18 @@<br>
 #<br>
 # @node: the name of the node that will be added.<br>
 #<br>
-# Note: this command is experimental, and its API is not stable. It<br>
-#       does not support all kinds of operations, all kinds of children, nor<br>
-#       all block drivers.<br>
+# Features:<br>
+# @unstable: This command is experimental, and its API is not stable.  It<br>
+#            does not support all kinds of operations, all kinds of<br>
+#            children, nor all block drivers.<br>
 #<br>
-#       FIXME Removing children from a quorum node means introducing gaps in the<br>
-#       child indices. This cannot be represented in the 'children' list of<br>
-#       BlockdevOptionsQuorum, as returned by .bdrv_refresh_filename().<br>
+#            FIXME Removing children from a quorum node means introducing<br>
+#            gaps in the child indices. This cannot be represented in the<br>
+#            'children' list of BlockdevOptionsQuorum, as returned by<br>
+#            .bdrv_refresh_filename().<br>
 #<br>
-#       Warning: The data in a new quorum child MUST be consistent with that of<br>
-#       the rest of the array.<br>
+#            Warning: The data in a new quorum child MUST be consistent<br>
+#            with that of the rest of the array.<br>
 #<br>
 # Since: 2.7<br>
 #<br>
@@ -5280,7 +5334,8 @@<br>
 { 'command': 'x-blockdev-change',<br>
   'data' : { 'parent': 'str',<br>
              '*child': 'str',<br>
-             '*node': 'str' } }<br>
+             '*node': 'str' },<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @x-blockdev-set-iothread:<br>
@@ -5297,8 +5352,9 @@<br>
 # @force: true if the node and its children should be moved when a BlockBackend<br>
 #         is already attached<br>
 #<br>
-# Note: this command is experimental and intended for test cases that need<br>
-#       control over IOThreads only.<br>
+# Features:<br>
+# @unstable: This command is experimental and intended for test cases that<br>
+#            need control over IOThreads only.<br>
 #<br>
 # Since: 2.12<br>
 #<br>
@@ -5320,7 +5376,8 @@<br>
 { 'command': 'x-blockdev-set-iothread',<br>
   'data' : { 'node-name': 'str',<br>
              'iothread': 'StrOrNull',<br>
-             '*force': 'bool' } }<br>
+             '*force': 'bool' },<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @QuorumOpType:<br>
diff --git a/qapi/migration.json b/qapi/migration.json<br>
index 88f07baedd..9aa8bc5759 100644<br>
--- a/qapi/migration.json<br>
+++ b/qapi/migration.json<br>
@@ -452,14 +452,20 @@<br>
 #                       procedure starts. The VM RAM is saved with running VM.<br>
 #                       (since 6.0)<br>
 #<br>
+# Features:<br>
+# @unstable: Members @x-colo and @x-ignore-shared are experimental.<br>
+#<br>
 # Since: 1.2<br>
 ##<br>
 { 'enum': 'MigrationCapability',<br>
   'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks',<br>
-           'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',<br>
+           'compress', 'events', 'postcopy-ram',<br>
+           { 'name': 'x-colo', 'features': [ 'unstable' ] },<br>
+           'release-ram',<br>
            'block', 'return-path', 'pause-before-switchover', 'multifd',<br>
            'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',<br>
-           'x-ignore-shared', 'validate-uuid', 'background-snapshot'] }<br>
+           { 'name': 'x-ignore-shared', 'features': [ 'unstable' ] },<br>
+           'validate-uuid', 'background-snapshot'] }<br>
<br>
 ##<br>
 # @MigrationCapabilityStatus:<br>
@@ -743,6 +749,9 @@<br>
 #                        block device name if there is one, and to their node name<br>
 #                        otherwise. (Since 5.2)<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-checkpoint-delay is experimental.<br>
+#<br>
 # Since: 2.4<br>
 ##<br>
 { 'enum': 'MigrationParameter',<br>
@@ -753,7 +762,9 @@<br>
            'cpu-throttle-initial', 'cpu-throttle-increment',<br>
            'cpu-throttle-tailslow',<br>
            'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth',<br>
-           'downtime-limit', 'x-checkpoint-delay', 'block-incremental',<br>
+           'downtime-limit',<br>
+           { 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] },<br>
+           'block-incremental',<br>
            'multifd-channels',<br>
            'xbzrle-cache-size', 'max-postcopy-bandwidth',<br>
            'max-cpu-throttle', 'multifd-compression',<br>
@@ -903,6 +914,9 @@<br>
 #                        block device name if there is one, and to their node name<br>
 #                        otherwise. (Since 5.2)<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-checkpoint-delay is experimental.<br>
+#<br>
 # Since: 2.4<br>
 ##<br>
 # TODO either fuse back into MigrationParameters, or make<br>
@@ -925,7 +939,8 @@<br>
             '*tls-authz': 'StrOrNull',<br>
             '*max-bandwidth': 'size',<br>
             '*downtime-limit': 'uint64',<br>
-            '*x-checkpoint-delay': 'uint32',<br>
+            '*x-checkpoint-delay': { 'type': 'uint32',<br>
+                                     'features': [ 'unstable' ] },<br>
             '*block-incremental': 'bool',<br>
             '*multifd-channels': 'uint8',<br>
             '*xbzrle-cache-size': 'size',<br>
@@ -1099,6 +1114,9 @@<br>
 #                        block device name if there is one, and to their node name<br>
 #                        otherwise. (Since 5.2)<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-checkpoint-delay is experimental.<br>
+#<br>
 # Since: 2.4<br>
 ##<br>
 { 'struct': 'MigrationParameters',<br>
@@ -1119,7 +1137,8 @@<br>
             '*tls-authz': 'str',<br>
             '*max-bandwidth': 'size',<br>
             '*downtime-limit': 'uint64',<br>
-            '*x-checkpoint-delay': 'uint32',<br>
+            '*x-checkpoint-delay': { 'type': 'uint32',<br>
+                                     'features': [ 'unstable' ] },<br>
             '*block-incremental': 'bool',<br>
             '*multifd-channels': 'uint8',<br>
             '*xbzrle-cache-size': 'size',<br>
@@ -1351,6 +1370,9 @@<br>
 # If sent to the Secondary, the Secondary side will run failover work,<br>
 # then takes over server operation to become the service VM.<br>
 #<br>
+# Features:<br>
+# @unstable: This command is experimental.<br>
+#<br>
 # Since: 2.8<br>
 #<br>
 # Example:<br>
@@ -1359,7 +1381,8 @@<br>
 # <- { "return": {} }<br>
 #<br>
 ##<br>
-{ 'command': 'x-colo-lost-heartbeat' }<br>
+{ 'command': 'x-colo-lost-heartbeat',<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @migrate_cancel:<br>
diff --git a/qapi/misc.json b/qapi/misc.json<br>
index 5c2ca3b556..358548abe1 100644<br>
--- a/qapi/misc.json<br>
+++ b/qapi/misc.json<br>
@@ -185,6 +185,9 @@<br>
 # available during the preconfig state (i.e. when the --preconfig command<br>
 # line option was in use).<br>
 #<br>
+# Features:<br>
+# @unstable: This command is experimental.<br>
+#<br>
 # Since 3.0<br>
 #<br>
 # Returns: nothing<br>
@@ -195,7 +198,8 @@<br>
 # <- { "return": {} }<br>
 #<br>
 ##<br>
-{ 'command': 'x-exit-preconfig', 'allow-preconfig': true }<br>
+{ 'command': 'x-exit-preconfig', 'allow-preconfig': true,<br>
+  'features': [ 'unstable' ] }<br>
<br>
 ##<br>
 # @human-monitor-command:<br>
diff --git a/qapi/qom.json b/qapi/qom.json<br>
index 7231ac3f34..ccd1167808 100644<br>
--- a/qapi/qom.json<br>
+++ b/qapi/qom.json<br>
@@ -559,10 +559,8 @@<br>
 #                                        for ramblock-id. Disable this for 4.0<br>
 #                                        machine types or older to allow<br>
 #                                        migration with newer QEMU versions.<br>
-#                                        This option is considered stable<br>
-#                                        despite the x- prefix. (default:<br>
-#                                        false generally, but true for machine<br>
-#                                        types <= 4.0)<br>
+#                                        (default: false generally,<br>
+#                                        but true for machine types <= 4.0)<br>
 #<br>
 # Note: prealloc=true and reserve=false cannot be set at the same time. With<br>
 #       reserve=true, the behavior depends on the operating system: for example,<br>
@@ -785,6 +783,9 @@<br>
 ##<br>
 # @ObjectType:<br>
 #<br>
+# Features:<br>
+# @unstable: Member @x-remote-object is experimental.<br>
+#<br>
 # Since: 6.0<br>
 ##<br>
 { 'enum': 'ObjectType',<br>
@@ -836,7 +837,7 @@<br>
     'tls-creds-psk',<br>
     'tls-creds-x509',<br>
     'tls-cipher-suites',<br>
-    'x-remote-object'<br>
+    { 'name': 'x-remote-object', 'features': [ 'unstable' ] }<br>
   ] }<br>
<br>
 ##<br>
-- <br>
2.31.1<br>
<br></blockquote><div><br></div><div>Seems OK, but I didn't audit for false positives/negatives. Trusting your judgment here. (It looks like Phil started to audit this in his reply to your previous commit, so I'll trust that.)</div><div><br></div><div>Acked-by: John Snow <<a href="mailto:jsnow@redhat.com">jsnow@redhat.com</a>><br></div></div></div>