softmmu: fix device deletion events with -device JSON syntax
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 not usable for its purpose, so
we add a new 'json-cli-hotplug' feature to indicate the
-device supports JSON without breaking hotplug.
Fixes: 5dacda5167
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/802
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20220105123847.4047954-2-berrange@redhat.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Tested-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
eac32e2232
commit
64b4529a43
@ -44,6 +44,9 @@
|
|||||||
# @json-cli: If present, the "-device" command line option supports JSON
|
# @json-cli: If present, the "-device" command line option supports JSON
|
||||||
# syntax with a structure identical to the arguments of this
|
# syntax with a structure identical to the arguments of this
|
||||||
# command.
|
# command.
|
||||||
|
# @json-cli-hotplug: If present, the "-device" command line option supports JSON
|
||||||
|
# syntax without the reference counting leak that broke
|
||||||
|
# hot-unplug
|
||||||
#
|
#
|
||||||
# Notes:
|
# Notes:
|
||||||
#
|
#
|
||||||
@ -74,7 +77,7 @@
|
|||||||
{ 'command': 'device_add',
|
{ 'command': 'device_add',
|
||||||
'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
|
'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
|
||||||
'gen': false, # so we can get the additional arguments
|
'gen': false, # so we can get the additional arguments
|
||||||
'features': ['json-cli'] }
|
'features': ['json-cli', 'json-cli-hotplug'] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @device_del:
|
# @device_del:
|
||||||
|
@ -2684,6 +2684,7 @@ static void qemu_create_cli_devices(void)
|
|||||||
qemu_opts_foreach(qemu_find_opts("device"),
|
qemu_opts_foreach(qemu_find_opts("device"),
|
||||||
device_init_func, NULL, &error_fatal);
|
device_init_func, NULL, &error_fatal);
|
||||||
QTAILQ_FOREACH(opt, &device_opts, next) {
|
QTAILQ_FOREACH(opt, &device_opts, next) {
|
||||||
|
DeviceState *dev;
|
||||||
loc_push_restore(&opt->loc);
|
loc_push_restore(&opt->loc);
|
||||||
/*
|
/*
|
||||||
* TODO Eventually we should call qmp_device_add() here to make sure it
|
* 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
|
* from the start, so call qdev_device_add_from_qdict() directly for
|
||||||
* now.
|
* 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);
|
loc_pop(&opt->loc);
|
||||||
}
|
}
|
||||||
rom_reset_order_override();
|
rom_reset_order_override();
|
||||||
|
@ -77,6 +77,23 @@ static void test_pci_unplug_request(void)
|
|||||||
qtest_quit(qtest);
|
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);
|
||||||
|
wait_device_deleted_event(qtest, "dev0");
|
||||||
|
|
||||||
|
qtest_quit(qtest);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_ccw_unplug(void)
|
static void test_ccw_unplug(void)
|
||||||
{
|
{
|
||||||
QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
|
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",
|
qtest_add_func("/device-plug/pci-unplug-request",
|
||||||
test_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")) {
|
if (!strcmp(arch, "s390x")) {
|
||||||
qtest_add_func("/device-plug/ccw-unplug",
|
qtest_add_func("/device-plug/ccw-unplug",
|
||||||
|
Loading…
Reference in New Issue
Block a user