On 05/01/2022 13:38, Daniel P. Berrangé wrote:
The -device JSON syntax impl leaks a reference on the created
DeviceState instance. As a result when you hot-unplug the
device, the device_finalize method won't be called and thus
it will fail to emit the required DEVICE_DELETED event.

A 'json-cli' feature was previously added against the
'device_add' QMP command QAPI schema to indicated to mgmt
apps that -device supported JSON syntax. Given the hotplug
bug that feature flag is no unusable for its purpose, so

Not sure to understand: do you mean "now unusable"?

we add a new 'json-cli-hotplug' feature to indicate the
-device supports JSON without breaking hotplug.

Fixes: https://gitlab.com/qemu-project/qemu/-/issues/802
Signed-off-by: Daniel P. Berrangé <berra...@redhat.com>
---
  qapi/qdev.json                 |  5 ++++-
  softmmu/vl.c                   |  4 +++-
  tests/qtest/device-plug-test.c | 19 +++++++++++++++++++
  3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/qapi/qdev.json b/qapi/qdev.json
index 69656b14df..26cd10106b 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -44,6 +44,9 @@
  # @json-cli: If present, the "-device" command line option supports JSON
  #            syntax with a structure identical to the arguments of this
  #            command.
+# @json-cli-hotplug: If present, the "-device" command line option supports 
JSON
+#                    syntax without the reference counting leak that broke
+#                    hot-unplug
  #
  # Notes:
  #
@@ -74,7 +77,7 @@
  { 'command': 'device_add',
    'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
    'gen': false, # so we can get the additional arguments
-  'features': ['json-cli'] }
+  'features': ['json-cli', 'json-cli-hotplug'] }
##
  # @device_del:
diff --git a/softmmu/vl.c b/softmmu/vl.c
index d9e4c619d3..b1fc7da104 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2684,6 +2684,7 @@ static void qemu_create_cli_devices(void)
      qemu_opts_foreach(qemu_find_opts("device"),
                        device_init_func, NULL, &error_fatal);
      QTAILQ_FOREACH(opt, &device_opts, next) {
+        DeviceState *dev;
          loc_push_restore(&opt->loc);
          /*
           * TODO Eventually we should call qmp_device_add() here to make sure 
it
@@ -2692,7 +2693,8 @@ static void qemu_create_cli_devices(void)
           * from the start, so call qdev_device_add_from_qdict() directly for
           * now.
           */
-        qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
+        dev = qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
+        object_unref(OBJECT(dev));
          loc_pop(&opt->loc);
      }
      rom_reset_order_override();
diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
index 559d47727a..ad79bd4c14 100644
--- a/tests/qtest/device-plug-test.c
+++ b/tests/qtest/device-plug-test.c
@@ -77,6 +77,23 @@ static void test_pci_unplug_request(void)
      qtest_quit(qtest);
  }
+static void test_pci_unplug_json_request(void)
+{
+    QTestState *qtest = qtest_initf(
+        "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'");
+
+    /*
+     * Request device removal. As the guest is not running, the request won't
+     * be processed. However during system reset, the removal will be
+     * handled, removing the device.
+     */
+    device_del(qtest, "dev0");
+    system_reset(qtest);

You can use qpci_unplug_acpi_device_test() to process the request... but I see this is done like that too in test_pci_unplug_request()

+    wait_device_deleted_event(qtest, "dev0");
+
+    qtest_quit(qtest);
+}
+
  static void test_ccw_unplug(void)
  {
      QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
@@ -145,6 +162,8 @@ int main(int argc, char **argv)
       */
      qtest_add_func("/device-plug/pci-unplug-request",
                     test_pci_unplug_request);
+    qtest_add_func("/device-plug/pci-unplug-json-request",
+                   test_pci_unplug_json_request);
if (!strcmp(arch, "s390x")) {
          qtest_add_func("/device-plug/ccw-unplug",

Reviewed-by: Laurent Vivier <lviv...@redhat.com>


Reply via email to