qdev currently represents a device's realization state with a single
boolean. This cannot distinguish a device that has never been realized
from one whose realization has failed or that has been unrealized, nor
can it represent realization in progress. Consequently, the same device
can enter DeviceClass::realize() reentrantly or more than once.
Supporting that complicates device implementations, and the behavior is
untested and likely broken.

This series first clarifies the division of work between
TypeInfo.instance_init, pre-realize property setting, and
DeviceClass::realize, including the implications of device introspection
and property-dependent child creation.

The remaining direct reads of DeviceState::realized are then converted
to qdev_is_realized(). Keeping users behind this accessor allows the
underlying lifecycle representation to change without exposing it; the
accessor is also made const so callers with a const DeviceState can use
it.

Before changing that representation, the series fixes an existing
qdev invariant. qdev_realize() can attach an unparented device to a
bus before giving it a QOM parent. A failure between those operations
leaves a bus child that object_unparent() cannot remove, causing
bus_unparent() to loop indefinitely. qdev_realize() now establishes
the QOM parent before attaching the device to its bus and rolls the
parent back on failure.

Finally, DeviceState::realized and the QOM realized property are
replaced with four explicit phases: initialized, realizing, realized,
and retired.
Entering the realizing phase before invoking callbacks prevents
reentrant realization. A failure after realization starts, or the start
of unrealization, moves the device to the terminal retired phase, so a
device's realize method is invoked at most once.

Signed-off-by: Akihiko Odaki <[email protected]>
---
Changes in v3:
- Ensured devices are QOM-parented before attaching them to a bus,
  avoiding unparentable bus children when realization fails.
- Clarified property-dependent child creation.
- Removed documentation references to the QOM realized property.
- Replaced DeviceState::realized and the QOM realized property with
  device phases. The realizing phase prevents reentrant realization, and
  the terminal retired phase prevents another attempt after realization
  fails or unrealization begins.
- Link to v2: 
https://lore.kernel.org/qemu-devel/[email protected]

Changes in v2:
- Clarified the ordering of #TypeInfo.instance_init, pre-realize
  property setting, and realization.
- Clarified that #TypeInfo.instance_init is for per-instance properties,
  not class properties.
- Link to v1: 
https://lore.kernel.org/qemu-devel/[email protected]

---
Akihiko Odaki (15):
      qdev: Clarify instantiation and realization
      qdev: Make qdev_is_realized() take a const DeviceState *
      hw/hyperv/balloon: Use qdev_is_realized()
      hw/intc/apic: Use qdev_is_realized()
      hw/mem/memory-device: Use qdev_is_realized()
      hw/mem/pc-dimm: Use qdev_is_realized()
      hw/nvram: Use qdev_is_realized()
      hw/ppc/pnv_xscom: Use qdev_is_realized()
      hw/vfio: Use qdev_is_realized()
      hw/virtio/virtio-mem: Use qdev_is_realized()
      hw/virtio/virtio-qmp: Use qdev_is_realized()
      target/i386/cpu: Use qdev_is_realized()
      target/s390x: Use qdev_is_realized()
      hw/qdev: Parent device before setting parent bus
      hw/qdev: Prevent devices from being realized more than once

 qapi/common.json           |  19 ++++++
 include/hw/core/qdev.h     |  62 ++++++++++---------
 hw/core/qdev-clock.c       |   4 +-
 hw/core/qdev-properties.c  |   4 +-
 hw/core/qdev.c             | 147 ++++++++++++++++++++++++++++-----------------
 hw/hyperv/hv-balloon.c     |   2 +-
 hw/intc/apic_common.c      |   2 +-
 hw/mem/memory-device.c     |   4 +-
 hw/mem/pc-dimm.c           |   2 +-
 hw/nvram/xlnx-bbram.c      |   2 +-
 hw/nvram/xlnx-efuse.c      |   2 +-
 hw/ppc/pnv_xscom.c         |   2 +-
 hw/scsi/scsi-bus.c         |   4 +-
 hw/vfio/container-legacy.c |   4 +-
 hw/vfio/device.c           |   4 +-
 hw/vfio/iommufd.c          |   2 +-
 hw/virtio/virtio-mem.c     |   4 +-
 hw/virtio/virtio-qmp.c     |   4 +-
 qom/qom-qmp-cmds.c         |   2 +-
 system/qdev-monitor.c      |   5 +-
 target/i386/cpu.c          |   2 +-
 target/s390x/cpu_models.c  |   4 +-
 tests/unit/test-qdev.c     | 125 +++++++++++++++++++++++++++++++++++++-
 23 files changed, 301 insertions(+), 111 deletions(-)
---
base-commit: 499039798cdad7d86b787fec0eaf1da4151c0f05
change-id: 20250906-qdev-9e5cb7c06ffa

Best regards,
--  
Akihiko Odaki <[email protected]>


Reply via email to