DeviceClass::hide() is a better alternative to DeviceListener::hide_device() that does not need listener registration and is contained in specific devices that need the hiding capability.
Signed-off-by: Akihiko Odaki <akihiko.od...@daynix.com> --- include/hw/qdev-core.h | 33 +++++++++++++++++++++++---------- system/qdev-monitor.c | 11 +++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 6befbca311..de221b6f02 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -56,16 +56,15 @@ * Hiding a device * --------------- * - * To hide a device, a DeviceListener function hide_device() needs to - * be registered. It can be used to defer adding a device and - * therefore hide it from the guest. The handler registering to this - * DeviceListener can save the QOpts passed to it for re-using it - * later. It must return if it wants the device to be hidden or - * visible. When the handler function decides the device shall be - * visible it will be added with qdev_device_add() and realized as any - * other device. Otherwise qdev_device_add() will return early without - * adding the device. The guest will not see a "hidden" device until - * it was marked visible and qdev_device_add called again. + * To hide a device, a DeviceClass function hide() needs to be registered. It + * can be used to defer adding a device and therefore hide it from the guest. + * The handler can save the QOpts passed to it for re-using it later. It must + * return if it wants the device to be hidden or visible. When the handler + * function decides the device shall be visible it will be added with + * qdev_device_add() and realized as any other device. Otherwise + * qdev_device_add() will return early without adding the device. The guest + * will not see a "hidden" device until it was marked visible and + * qdev_device_add called again. * */ @@ -90,6 +89,8 @@ typedef enum DeviceCategory { DEVICE_CATEGORY_MAX } DeviceCategory; +typedef bool (*DeviceHide)(DeviceClass *dc, const QDict *device_opts, + bool from_json, Error **errp); typedef void (*DeviceRealize)(DeviceState *dev, Error **errp); typedef void (*DeviceUnrealize)(DeviceState *dev); typedef void (*DeviceReset)(DeviceState *dev); @@ -151,6 +152,18 @@ struct DeviceClass { bool hotpluggable; /* callbacks */ + /** + * @hide: informs qdev if a device should be visible or hidden. + * + * This callback is called upon init of the DeviceState. + * We can hide a failover device depending for example on the device + * opts. + * + * On errors, it returns false and errp is set. Device creation + * should fail in this case. + */ + DeviceHide hide; + /** * @reset: deprecated device reset method pointer * diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 71c00f62ee..639beabc5f 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -669,6 +669,17 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, return NULL; } + if (dc->hide) { + if (dc->hide(dc, opts, from_json, errp)) { + if (bus && !qbus_is_hotpluggable(bus)) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); + } + return NULL; + } else if (*errp) { + return NULL; + } + } + if (phase_check(PHASE_MACHINE_READY) && bus && !qbus_is_hotpluggable(bus)) { error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name); return NULL; -- 2.43.0