* [Qemu-devel] [PATCH v2 0/2] Check for the availability of a hotplug controller before adding a device
@ 2017-10-05 12:32 Thomas Huth
2017-10-05 12:32 ` [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add() Thomas Huth
2017-10-05 12:32 ` [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device Thomas Huth
0 siblings, 2 replies; 6+ messages in thread
From: Thomas Huth @ 2017-10-05 12:32 UTC (permalink / raw)
To: qemu-devel, Eduardo Habkost
Cc: Markus Armbruster, Dr. David Alan Gilbert, Igor Mammedov, Paolo Bonzini
First patch is a small clean up to the error handling code in
qdev_device_add(), and the second patch adds a proper check for
the availability of a hotplug controller to prevent the possibility
of a crash with device_del.
Thomas Huth (2):
qdev_monitor: Simplify error handling in qdev_device_add()
qdev: Check for the availability of a hotplug controller before adding
a device
hw/core/qdev.c | 28 ++++++++++++++++++++--------
include/hw/qdev-core.h | 1 +
qdev-monitor.c | 26 +++++++++++++++-----------
3 files changed, 36 insertions(+), 19 deletions(-)
--
1.8.3.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add()
2017-10-05 12:32 [Qemu-devel] [PATCH v2 0/2] Check for the availability of a hotplug controller before adding a device Thomas Huth
@ 2017-10-05 12:32 ` Thomas Huth
2017-10-05 13:59 ` Igor Mammedov
2017-10-05 12:32 ` [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device Thomas Huth
1 sibling, 1 reply; 6+ messages in thread
From: Thomas Huth @ 2017-10-05 12:32 UTC (permalink / raw)
To: qemu-devel, Eduardo Habkost
Cc: Markus Armbruster, Dr. David Alan Gilbert, Igor Mammedov, Paolo Bonzini
Instead of doing the clean-ups on errors multiple times, introduce
a jump label at the end of the function that can be used by all
error paths that need this cleanup.
Suggested-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
qdev-monitor.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 8fd6df9..cb2b109 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -620,22 +620,21 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
/* set properties */
if (qemu_opt_foreach(opts, set_property, dev, &err)) {
- error_propagate(errp, err);
- object_unparent(OBJECT(dev));
- object_unref(OBJECT(dev));
- return NULL;
+ goto err_del_dev;
}
dev->opts = opts;
object_property_set_bool(OBJECT(dev), true, "realized", &err);
- if (err != NULL) {
- error_propagate(errp, err);
- dev->opts = NULL;
- object_unparent(OBJECT(dev));
- object_unref(OBJECT(dev));
- return NULL;
+ if (!err) {
+ return dev;
}
- return dev;
+ dev->opts = NULL;
+
+err_del_dev:
+ error_propagate(errp, err);
+ object_unparent(OBJECT(dev));
+ object_unref(OBJECT(dev));
+ return NULL;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device
2017-10-05 12:32 [Qemu-devel] [PATCH v2 0/2] Check for the availability of a hotplug controller before adding a device Thomas Huth
2017-10-05 12:32 ` [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add() Thomas Huth
@ 2017-10-05 12:32 ` Thomas Huth
2017-10-05 14:13 ` Igor Mammedov
1 sibling, 1 reply; 6+ messages in thread
From: Thomas Huth @ 2017-10-05 12:32 UTC (permalink / raw)
To: qemu-devel, Eduardo Habkost
Cc: Markus Armbruster, Dr. David Alan Gilbert, Igor Mammedov, Paolo Bonzini
The qdev_unplug() function contains a g_assert(hotplug_ctrl) statement,
so QEMU crashes when the user tries to device_add + device_del a device
that does not have a corresponding hotplug controller. This could be
provoked for a couple of devices in the past (see commit 4c93950659487c7ad
or 84ebd3e8c7d4fe955 for example). So devices clearly need a hotplug
controller when they should be usable with device_add.
The code in qdev_device_add() already checks whether the bus has a proper
hotplug controller, but for devices that do not have a corresponding bus,
there is no appropriate check available yet. In that case we should check
whether the machine itself provides a suitable hotplug controller and
refuse to plug the device if none is available.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
v2:
- Do the check earlier in qdev_device_add
- Use common new err_dev_del handler in case of failure
hw/core/qdev.c | 28 ++++++++++++++++++++--------
include/hw/qdev-core.h | 1 +
qdev-monitor.c | 5 +++++
3 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 606ab53..a953ec9 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -253,19 +253,31 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
dev->alias_required_for_version = required_for_version;
}
+HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
+{
+ MachineState *machine;
+ MachineClass *mc;
+ Object *m_obj = qdev_get_machine();
+
+ if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
+ machine = MACHINE(m_obj);
+ mc = MACHINE_GET_CLASS(machine);
+ if (mc->get_hotplug_handler) {
+ return mc->get_hotplug_handler(machine, dev);
+ }
+ }
+
+ return NULL;
+}
+
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
{
- HotplugHandler *hotplug_ctrl = NULL;
+ HotplugHandler *hotplug_ctrl;
if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
hotplug_ctrl = dev->parent_bus->hotplug_handler;
- } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
- MachineState *machine = MACHINE(qdev_get_machine());
- MachineClass *mc = MACHINE_GET_CLASS(machine);
-
- if (mc->get_hotplug_handler) {
- hotplug_ctrl = mc->get_hotplug_handler(machine, dev);
- }
+ } else {
+ hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
}
return hotplug_ctrl;
}
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 0891461..5aa536d 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -285,6 +285,7 @@ DeviceState *qdev_try_create(BusState *bus, const char *name);
void qdev_init_nofail(DeviceState *dev);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
+HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
diff --git a/qdev-monitor.c b/qdev-monitor.c
index cb2b109..f93455f 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -614,6 +614,11 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
if (bus) {
qdev_set_parent_bus(dev, bus);
+ } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
+ /* No bus, no machine hotplug handler --> device is not hotpluggable */
+ error_setg(&err, "Device '%s' can not be hotplugged on this machine",
+ driver);
+ goto err_del_dev;
}
qdev_set_id(dev, qemu_opts_id(opts));
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add()
2017-10-05 12:32 ` [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add() Thomas Huth
@ 2017-10-05 13:59 ` Igor Mammedov
2017-10-05 17:11 ` Eduardo Habkost
0 siblings, 1 reply; 6+ messages in thread
From: Igor Mammedov @ 2017-10-05 13:59 UTC (permalink / raw)
To: Thomas Huth
Cc: qemu-devel, Eduardo Habkost, Markus Armbruster,
Dr. David Alan Gilbert, Paolo Bonzini
On Thu, 5 Oct 2017 14:32:17 +0200
Thomas Huth <thuth@redhat.com> wrote:
> Instead of doing the clean-ups on errors multiple times, introduce
> a jump label at the end of the function that can be used by all
> error paths that need this cleanup.
>
> Suggested-by: Igor Mammedov <imammedo@redhat.com>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
> ---
> qdev-monitor.c | 21 ++++++++++-----------
> 1 file changed, 10 insertions(+), 11 deletions(-)
>
> diff --git a/qdev-monitor.c b/qdev-monitor.c
> index 8fd6df9..cb2b109 100644
> --- a/qdev-monitor.c
> +++ b/qdev-monitor.c
> @@ -620,22 +620,21 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
>
> /* set properties */
> if (qemu_opt_foreach(opts, set_property, dev, &err)) {
> - error_propagate(errp, err);
> - object_unparent(OBJECT(dev));
> - object_unref(OBJECT(dev));
> - return NULL;
> + goto err_del_dev;
> }
>
> dev->opts = opts;
> object_property_set_bool(OBJECT(dev), true, "realized", &err);
> - if (err != NULL) {
> - error_propagate(errp, err);
> - dev->opts = NULL;
> - object_unparent(OBJECT(dev));
> - object_unref(OBJECT(dev));
> - return NULL;
> + if (!err) {
> + return dev;
> }
typically the same error check pattern is used through out the function
so I'd not do inversion here. i.e. keep normal flow non-branched and jump on error
if (err != NULL) {
goto err_del_dev;
}
return dev;
err_del_dev:
dev->opts = NULL;
> - return dev;
> + dev->opts = NULL;
> +
> +err_del_dev:
> + error_propagate(errp, err);
> + object_unparent(OBJECT(dev));
> + object_unref(OBJECT(dev));
> + return NULL;
> }
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device
2017-10-05 12:32 ` [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device Thomas Huth
@ 2017-10-05 14:13 ` Igor Mammedov
0 siblings, 0 replies; 6+ messages in thread
From: Igor Mammedov @ 2017-10-05 14:13 UTC (permalink / raw)
To: Thomas Huth
Cc: qemu-devel, Eduardo Habkost, Markus Armbruster,
Dr. David Alan Gilbert, Paolo Bonzini
On Thu, 5 Oct 2017 14:32:18 +0200
Thomas Huth <thuth@redhat.com> wrote:
> The qdev_unplug() function contains a g_assert(hotplug_ctrl) statement,
> so QEMU crashes when the user tries to device_add + device_del a device
> that does not have a corresponding hotplug controller. This could be
> provoked for a couple of devices in the past (see commit 4c93950659487c7ad
> or 84ebd3e8c7d4fe955 for example). So devices clearly need a hotplug
> controller when they should be usable with device_add.
> The code in qdev_device_add() already checks whether the bus has a proper
> hotplug controller, but for devices that do not have a corresponding bus,
> there is no appropriate check available yet. In that case we should check
> whether the machine itself provides a suitable hotplug controller and
> refuse to plug the device if none is available.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> ---
> v2:
> - Do the check earlier in qdev_device_add
> - Use common new err_dev_del handler in case of failure
>
> hw/core/qdev.c | 28 ++++++++++++++++++++--------
> include/hw/qdev-core.h | 1 +
> qdev-monitor.c | 5 +++++
> 3 files changed, 26 insertions(+), 8 deletions(-)
>
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 606ab53..a953ec9 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -253,19 +253,31 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> dev->alias_required_for_version = required_for_version;
> }
>
> +HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
> +{
> + MachineState *machine;
> + MachineClass *mc;
> + Object *m_obj = qdev_get_machine();
> +
> + if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
> + machine = MACHINE(m_obj);
> + mc = MACHINE_GET_CLASS(machine);
> + if (mc->get_hotplug_handler) {
> + return mc->get_hotplug_handler(machine, dev);
> + }
> + }
> +
> + return NULL;
> +}
> +
> HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
> {
> - HotplugHandler *hotplug_ctrl = NULL;
> + HotplugHandler *hotplug_ctrl;
>
> if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
> hotplug_ctrl = dev->parent_bus->hotplug_handler;
> - } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
> - MachineState *machine = MACHINE(qdev_get_machine());
> - MachineClass *mc = MACHINE_GET_CLASS(machine);
> -
> - if (mc->get_hotplug_handler) {
> - hotplug_ctrl = mc->get_hotplug_handler(machine, dev);
> - }
> + } else {
> + hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
> }
> return hotplug_ctrl;
> }
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 0891461..5aa536d 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -285,6 +285,7 @@ DeviceState *qdev_try_create(BusState *bus, const char *name);
> void qdev_init_nofail(DeviceState *dev);
> void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
> int required_for_version);
> +HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev);
> HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
> void qdev_unplug(DeviceState *dev, Error **errp);
> void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
> diff --git a/qdev-monitor.c b/qdev-monitor.c
> index cb2b109..f93455f 100644
> --- a/qdev-monitor.c
> +++ b/qdev-monitor.c
> @@ -614,6 +614,11 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
>
> if (bus) {
> qdev_set_parent_bus(dev, bus);
> + } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
> + /* No bus, no machine hotplug handler --> device is not hotpluggable */
> + error_setg(&err, "Device '%s' can not be hotplugged on this machine",
> + driver);
> + goto err_del_dev;
> }
>
> qdev_set_id(dev, qemu_opts_id(opts));
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add()
2017-10-05 13:59 ` Igor Mammedov
@ 2017-10-05 17:11 ` Eduardo Habkost
0 siblings, 0 replies; 6+ messages in thread
From: Eduardo Habkost @ 2017-10-05 17:11 UTC (permalink / raw)
To: Igor Mammedov
Cc: Thomas Huth, qemu-devel, Markus Armbruster,
Dr. David Alan Gilbert, Paolo Bonzini
On Thu, Oct 05, 2017 at 03:59:12PM +0200, Igor Mammedov wrote:
> On Thu, 5 Oct 2017 14:32:17 +0200
> Thomas Huth <thuth@redhat.com> wrote:
>
> > Instead of doing the clean-ups on errors multiple times, introduce
> > a jump label at the end of the function that can be used by all
> > error paths that need this cleanup.
> >
> > Suggested-by: Igor Mammedov <imammedo@redhat.com>
> > Signed-off-by: Thomas Huth <thuth@redhat.com>
> > ---
> > qdev-monitor.c | 21 ++++++++++-----------
> > 1 file changed, 10 insertions(+), 11 deletions(-)
> >
> > diff --git a/qdev-monitor.c b/qdev-monitor.c
> > index 8fd6df9..cb2b109 100644
> > --- a/qdev-monitor.c
> > +++ b/qdev-monitor.c
> > @@ -620,22 +620,21 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
> >
> > /* set properties */
> > if (qemu_opt_foreach(opts, set_property, dev, &err)) {
> > - error_propagate(errp, err);
> > - object_unparent(OBJECT(dev));
> > - object_unref(OBJECT(dev));
> > - return NULL;
> > + goto err_del_dev;
> > }
> >
> > dev->opts = opts;
> > object_property_set_bool(OBJECT(dev), true, "realized", &err);
> > - if (err != NULL) {
> > - error_propagate(errp, err);
> > - dev->opts = NULL;
> > - object_unparent(OBJECT(dev));
> > - object_unref(OBJECT(dev));
> > - return NULL;
> > + if (!err) {
> > + return dev;
> > }
> typically the same error check pattern is used through out the function
> so I'd not do inversion here. i.e. keep normal flow non-branched and jump on error
>
> if (err != NULL) {
> goto err_del_dev;
> }
> return dev;
>
> err_del_dev:
> dev->opts = NULL;
I prefer this pattern also. It makes the success/error paths
very easy to spot.
--
Eduardo
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-10-05 17:12 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-05 12:32 [Qemu-devel] [PATCH v2 0/2] Check for the availability of a hotplug controller before adding a device Thomas Huth
2017-10-05 12:32 ` [Qemu-devel] [PATCH 1/2] qdev_monitor: Simplify error handling in qdev_device_add() Thomas Huth
2017-10-05 13:59 ` Igor Mammedov
2017-10-05 17:11 ` Eduardo Habkost
2017-10-05 12:32 ` [Qemu-devel] [PATCH v2 2/2] qdev: Check for the availability of a hotplug controller before adding a device Thomas Huth
2017-10-05 14:13 ` Igor Mammedov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.