From: "Michael S. Tsirkin" <mst@redhat.com>
To: "Andreas Färber" <afaerber@suse.de>
Cc: Kevin Wolf <kwolf@redhat.com>,
Anthony Liguori <aliguori@us.ibm.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
qemu-devel@nongnu.org, jlarrew@linux.vnet.ibm.com,
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>,
anthony@codemonkey.ws, Amit Shah <amit.shah@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>,
fred.konrad@greensocs.com
Subject: Re: [Qemu-devel] [PATCH RFT 2/5] virtio: Convert VirtioDevice to QOM realize/unrealize
Date: Sun, 9 Jun 2013 13:36:49 +0300 [thread overview]
Message-ID: <20130609103649.GE14832@redhat.com> (raw)
In-Reply-To: <1370629140-30841-3-git-send-email-afaerber@suse.de>
On Fri, Jun 07, 2013 at 08:18:57PM +0200, Andreas Färber wrote:
> VirtioDevice's DeviceClass::exit code cleaning up bus_name is no longer
> overwritten by virtio-{blk,serial,net,scsi,balloon,rng} and vhost-scsi.
>
> Note: VirtIOSCSI and VHostSCSI now perform some initializations after
> VirtIOSCSICommon's realize calls virtio_bus_plug_device(), namely
> creating the SCSIBus and initializing /dev/vhost-scsi respectively.
>
> While at it, drop duplicate VIRTIO_DEVICE() casts and avoid qdev.
There are also improvements to error handling here, they can
be done by a separate patch.
Please don't mix refactoring and functional changes -
this patch is huge as it is.
Also, could changes to each device be done in a separate patch?
This last might be hard, not a must IMO.
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
> hw/9pfs/virtio-9p-device.c | 67 ++++++++++++++++--------------
> hw/9pfs/virtio-9p.h | 13 ++++++
> hw/block/virtio-blk.c | 52 ++++++++++++++---------
> hw/char/virtio-serial-bus.c | 49 ++++++++++++++--------
> hw/net/virtio-net.c | 48 ++++++++++++---------
> hw/scsi/vhost-scsi.c | 59 +++++++++++++++-----------
> hw/scsi/virtio-scsi.c | 85 ++++++++++++++++++++++++--------------
> hw/virtio/virtio-balloon.c | 50 +++++++++++++---------
> hw/virtio/virtio-rng.c | 53 ++++++++++++++----------
> hw/virtio/virtio.c | 20 ++++-----
> include/hw/virtio/vhost-scsi.h | 13 ++++++
> include/hw/virtio/virtio-balloon.h | 13 ++++++
> include/hw/virtio/virtio-blk.h | 13 ++++++
> include/hw/virtio/virtio-net.h | 13 ++++++
> include/hw/virtio/virtio-rng.h | 13 ++++++
> include/hw/virtio/virtio-scsi.h | 29 +++++++++++--
> include/hw/virtio/virtio-serial.h | 13 ++++++
> include/hw/virtio/virtio.h | 6 ++-
> 18 files changed, 406 insertions(+), 203 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
> index dc6f4e4..409d315 100644
> --- a/hw/9pfs/virtio-9p-device.c
> +++ b/hw/9pfs/virtio-9p-device.c
> @@ -41,15 +41,17 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
> g_free(cfg);
> }
>
> -static int virtio_9p_device_init(VirtIODevice *vdev)
> +static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
> {
> - V9fsState *s = VIRTIO_9P(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + V9fsState *s = VIRTIO_9P(dev);
> + V9fsClass *v9c = VIRTIO_9P_GET_CLASS(dev);
> int i, len;
> struct stat stat;
> FsDriverEntry *fse;
> V9fsPath path;
>
> - virtio_init(VIRTIO_DEVICE(s), "virtio-9p", VIRTIO_ID_9P,
> + virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P,
> sizeof(struct virtio_9p_config) + MAX_TAG_LEN);
>
> /* initialize pdu allocator */
> @@ -65,17 +67,17 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
>
> if (!fse) {
> /* We don't have a fsdev identified by fsdev_id */
> - fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
> - "id = %s\n",
> - s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
> - return -1;
> + error_setg(errp, "Virtio-9p device couldn't find fsdev with the "
> + "id = %s",
> + s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
> + return;
> }
>
> if (!s->fsconf.tag) {
> /* we haven't specified a mount_tag */
> - fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
> - s->fsconf.fsdev_id);
> - return -1;
> + error_setg(errp, "fsdev with id %s needs mount_tag arguments",
> + s->fsconf.fsdev_id);
> + return;
> }
>
> s->ctx.export_flags = fse->export_flags;
> @@ -83,9 +85,9 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
> s->ctx.exops.get_st_gen = NULL;
> len = strlen(s->fsconf.tag);
> if (len > MAX_TAG_LEN - 1) {
> - fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
> - "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
> - return -1;
> + error_setg(errp, "mount tag '%s' (%d bytes) is longer than "
> + "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
> + return;
> }
>
> s->tag = strdup(s->fsconf.tag);
> @@ -97,13 +99,13 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
> qemu_co_rwlock_init(&s->rename_lock);
>
> if (s->ops->init(&s->ctx) < 0) {
> - fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s"
> - " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root);
> - return -1;
> + error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s"
> + " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root);
> + return;
> }
> if (v9fs_init_worker_threads() < 0) {
> - fprintf(stderr, "worker thread initialization failed\n");
> - return -1;
> + error_setg(errp, "worker thread initialization failed");
> + return;
> }
>
> /*
> @@ -113,20 +115,20 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
> */
> v9fs_path_init(&path);
> if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
> - fprintf(stderr,
> - "error in converting name to path %s", strerror(errno));
> - return -1;
> + error_setg(errp,
> + "error in converting name to path %s", strerror(errno));
> + return;
> }
> if (s->ops->lstat(&s->ctx, &path, &stat)) {
> - fprintf(stderr, "share path %s does not exist\n", fse->path);
> - return -1;
> + error_setg(errp, "share path %s does not exist", fse->path);
> + return;
> } else if (!S_ISDIR(stat.st_mode)) {
> - fprintf(stderr, "share path %s is not a directory\n", fse->path);
> - return -1;
> + error_setg(errp, "share path %s is not a directory", fse->path);
> + return;
> }
> v9fs_path_free(&path);
>
> - return 0;
> + v9c->parent_realize(dev, errp);
> }
>
> /* virtio-9p device */
> @@ -136,12 +138,16 @@ static Property virtio_9p_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_9p_class_init(ObjectClass *klass, void *data)
> +static void virtio_9p_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + V9fsClass *v9c = VIRTIO_9P_CLASS(oc);
> +
> + v9c->parent_realize = dc->realize;
> + dc->realize = virtio_9p_device_realize;
> +
> dc->props = virtio_9p_properties;
> - vdc->init = virtio_9p_device_init;
> vdc->get_features = virtio_9p_get_features;
> vdc->get_config = virtio_9p_get_config;
> }
> @@ -151,6 +157,7 @@ static const TypeInfo virtio_device_info = {
> .parent = TYPE_VIRTIO_DEVICE,
> .instance_size = sizeof(V9fsState),
> .class_init = virtio_9p_class_init,
> + .class_size = sizeof(V9fsClass),
> };
>
> static void virtio_9p_register_types(void)
> diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
> index 1d6eedb..85699a7 100644
> --- a/hw/9pfs/virtio-9p.h
> +++ b/hw/9pfs/virtio-9p.h
> @@ -227,6 +227,15 @@ typedef struct V9fsState
> V9fsConf fsconf;
> } V9fsState;
>
> +typedef struct V9fsClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> +} V9fsClass;
> +
> +
One empty line please.
> typedef struct V9fsStatState {
> V9fsPDU *pdu;
> size_t offset;
> @@ -404,6 +413,10 @@ extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
> #define TYPE_VIRTIO_9P "virtio-9p-device"
> #define VIRTIO_9P(obj) \
> OBJECT_CHECK(V9fsState, (obj), TYPE_VIRTIO_9P)
> +#define VIRTIO_9P_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(V9fsClass, (obj), TYPE_VIRTIO_9P)
> +#define VIRTIO_9P_CLASS(cls) \
> + OBJECT_CLASS_CHECK(V9fsClass, (cls), TYPE_VIRTIO_9P)
>
> #define DEFINE_VIRTIO_9P_PROPERTIES(_state, _field) \
> DEFINE_PROP_STRING("mount_tag", _state, _field.tag), \
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 8ea1f03..88e99a6 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -628,10 +628,11 @@ void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk)
> memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
> }
>
> -static int virtio_blk_device_init(VirtIODevice *vdev)
> +static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
> {
> - DeviceState *qdev = DEVICE(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> VirtIOBlock *s = VIRTIO_BLK(vdev);
> + VirtIOBlockClass *vbc = VIRTIO_BLK_GET_CLASS(dev);
> VirtIOBlkConf *blk = &(s->blk);
> #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
> Error *err = NULL;
> @@ -639,17 +640,18 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
> static int virtio_blk_id;
>
> if (!blk->conf.bs) {
> - error_report("drive property not set");
> - return -1;
> + error_setg(errp, "drive property not set");
> + return;
> }
> if (!bdrv_is_inserted(blk->conf.bs)) {
> - error_report("Device needs media, but drive is empty");
> - return -1;
> + error_setg(errp, "Device needs media, but drive is empty");
> + return;
> }
>
> blkconf_serial(&blk->conf, &blk->serial);
> if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
> - return -1;
> + error_setg(errp, "Error setting geometry");
> + return;
> }
>
> virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
> @@ -665,29 +667,31 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
> #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
> virtio_blk_data_plane_create(vdev, blk, &s->dataplane, &err);
> if (err != NULL) {
> - error_report("%s", error_get_pretty(err));
> - error_free(err);
> + error_propagate(errp, err);
> virtio_cleanup(vdev);
> - return -1;
> + return;
> }
> #endif
>
> s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
> - register_savevm(qdev, "virtio-blk", virtio_blk_id++, 2,
> + register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
> virtio_blk_save, virtio_blk_load, s);
> bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
> bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
>
> bdrv_iostatus_enable(s->bs);
>
> - add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0");
> - return 0;
> + add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
> +
> + vbc->parent_realize(dev, errp);
> }
>
> -static int virtio_blk_device_exit(DeviceState *dev)
> +static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
> {
> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> VirtIOBlock *s = VIRTIO_BLK(dev);
> + VirtIOBlockClass *vbc = VIRTIO_BLK_GET_CLASS(dev);
> +
> #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
> virtio_blk_data_plane_destroy(s->dataplane);
> s->dataplane = NULL;
> @@ -696,7 +700,8 @@ static int virtio_blk_device_exit(DeviceState *dev)
> unregister_savevm(dev, "virtio-blk", s);
> blockdev_mark_auto_del(s->bs);
> virtio_cleanup(vdev);
> - return 0;
> +
> + vbc->parent_unrealize(dev, errp);
> }
>
> static Property virtio_blk_properties[] = {
> @@ -704,13 +709,19 @@ static Property virtio_blk_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_blk_class_init(ObjectClass *klass, void *data)
> +static void virtio_blk_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_blk_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIOBlockClass *vbc = VIRTIO_BLK_CLASS(oc);
> +
> + vbc->parent_realize = dc->realize;
> + dc->realize = virtio_blk_device_realize;
> +
> + vbc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_blk_device_unrealize;
> +
> dc->props = virtio_blk_properties;
> - vdc->init = virtio_blk_device_init;
> vdc->get_config = virtio_blk_update_config;
> vdc->set_config = virtio_blk_set_config;
> vdc->get_features = virtio_blk_get_features;
> @@ -723,6 +734,7 @@ static const TypeInfo virtio_device_info = {
> .parent = TYPE_VIRTIO_DEVICE,
> .instance_size = sizeof(VirtIOBlock),
> .class_init = virtio_blk_class_init,
> + .class_size = sizeof(VirtIOBlockClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
> index cc3d1dd..1cdd659 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -889,31 +889,35 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
> return 0;
> }
>
> -static int virtio_serial_device_init(VirtIODevice *vdev)
> +static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
> {
> - DeviceState *qdev = DEVICE(vdev);
> - VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSerial *vser = VIRTIO_SERIAL(dev);
> + VirtIOSerialClass *vsc = VIRTIO_SERIAL_GET_CLASS(dev);
> + BusState *bus;
> uint32_t i, max_supported_ports;
>
> if (!vser->serial.max_virtserial_ports) {
> - return -1;
> + error_setg(errp, "Maximum number of serial ports not specified");
> + return;
> }
>
> /* Each port takes 2 queues, and one pair is for the control queue */
> max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
>
> if (vser->serial.max_virtserial_ports > max_supported_ports) {
> - error_report("maximum ports supported: %u", max_supported_ports);
> - return -1;
> + error_setg(errp, "maximum ports supported: %u", max_supported_ports);
> + return;
> }
>
> virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE,
> sizeof(struct virtio_console_config));
>
> /* Spawn a new virtio-serial bus on which the ports will ride as devices */
> - qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, qdev,
> + qbus_create_inplace(&vser->bus, TYPE_VIRTIO_SERIAL_BUS, dev,
> vdev->bus_name);
> - vser->bus.qbus.allow_hotplug = 1;
> + bus = BUS(&vser->bus);
> + bus->allow_hotplug = 1;
> vser->bus.vser = vser;
> QTAILQ_INIT(&vser->ports);
>
> @@ -961,10 +965,10 @@ static int virtio_serial_device_init(VirtIODevice *vdev)
> * Register for the savevm section with the virtio-console name
> * to preserve backward compat
> */
> - register_savevm(qdev, "virtio-console", -1, 3, virtio_serial_save,
> + register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
> virtio_serial_load, vser);
>
> - return 0;
> + vsc->parent_realize(dev, errp);
> }
>
> static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
> @@ -986,10 +990,11 @@ static const TypeInfo virtio_serial_port_type_info = {
> .class_init = virtio_serial_port_class_init,
> };
>
> -static int virtio_serial_device_exit(DeviceState *dev)
> +static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIOSerial *vser = VIRTIO_SERIAL(dev);
> VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSerial *vser = VIRTIO_SERIAL(dev);
> + VirtIOSerialClass *vsc = VIRTIO_SERIAL_GET_CLASS(dev);
>
> unregister_savevm(dev, "virtio-console", vser);
>
> @@ -1003,7 +1008,8 @@ static int virtio_serial_device_exit(DeviceState *dev)
> g_free(vser->post_load);
> }
> virtio_cleanup(vdev);
> - return 0;
> +
> + vsc->parent_unrealize(dev, errp);
> }
>
> static Property virtio_serial_properties[] = {
> @@ -1011,13 +1017,19 @@ static Property virtio_serial_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_serial_class_init(ObjectClass *klass, void *data)
> +static void virtio_serial_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_serial_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIOSerialClass *vsc = VIRTIO_SERIAL_CLASS(oc);
> +
> + vsc->parent_realize = dc->realize;
> + dc->realize = virtio_serial_device_realize;
> +
> + vsc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_serial_device_unrealize;
> +
> dc->props = virtio_serial_properties;
> - vdc->init = virtio_serial_device_init;
> vdc->get_features = get_features;
> vdc->get_config = get_config;
> vdc->set_config = set_config;
> @@ -1030,6 +1042,7 @@ static const TypeInfo virtio_device_info = {
> .parent = TYPE_VIRTIO_DEVICE,
> .instance_size = sizeof(VirtIOSerial),
> .class_init = virtio_serial_class_init,
> + .class_size = sizeof(VirtIOSerialClass),
> };
>
> static void virtio_serial_register_types(void)
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 1ea9556..9a3680c 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -1367,15 +1367,16 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
> n->netclient_type = g_strdup(type);
> }
>
> -static int virtio_net_device_init(VirtIODevice *vdev)
> +static void virtio_net_device_realize(DeviceState *dev, Error **errp)
> {
> int i;
>
> - DeviceState *qdev = DEVICE(vdev);
> - VirtIONet *n = VIRTIO_NET(vdev);
> + DeviceState *qdev = DEVICE(dev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIONet *n = VIRTIO_NET(dev);
> + VirtIONetClass *vnc = VIRTIO_NET_GET_CLASS(dev);
>
> - virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
> - n->config_size);
> + virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
>
> n->max_queues = MAX(n->nic_conf.queues, 1);
> n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
> @@ -1439,24 +1440,26 @@ static int virtio_net_device_init(VirtIODevice *vdev)
>
> n->vlans = g_malloc0(MAX_VLAN >> 3);
>
> - n->qdev = qdev;
> - register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
> + n->qdev = dev;
> + register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
> virtio_net_save, virtio_net_load, n);
>
> - add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0");
> - return 0;
> + add_boot_device_path(n->nic_conf.bootindex, dev, "/ethernet-phy@0");
> +
> + vnc->parent_realize(dev, errp);
> }
>
> -static int virtio_net_device_exit(DeviceState *qdev)
> +static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIONet *n = VIRTIO_NET(qdev);
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIONet *n = VIRTIO_NET(dev);
> + VirtIONetClass *vnc = VIRTIO_NET_GET_CLASS(dev);
> int i;
>
> /* This will stop vhost backend if appropriate. */
> virtio_net_set_status(vdev, 0);
>
> - unregister_savevm(qdev, "virtio-net", n);
> + unregister_savevm(dev, "virtio-net", n);
>
> if (n->netclient_name) {
> g_free(n->netclient_name);
> @@ -1488,7 +1491,7 @@ static int virtio_net_device_exit(DeviceState *qdev)
> qemu_del_nic(n->nic);
> virtio_cleanup(vdev);
>
> - return 0;
> + vnc->parent_unrealize(dev, errp);
> }
>
> static void virtio_net_instance_init(Object *obj)
> @@ -1511,13 +1514,19 @@ static Property virtio_net_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_net_class_init(ObjectClass *klass, void *data)
> +static void virtio_net_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_net_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIONetClass *vnc = VIRTIO_NET_CLASS(oc);
> +
> + vnc->parent_realize = dc->realize;
> + dc->realize = virtio_net_device_realize;
> +
> + vnc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_net_device_unrealize;
> +
> dc->props = virtio_net_properties;
> - vdc->init = virtio_net_device_init;
> vdc->get_config = virtio_net_get_config;
> vdc->set_config = virtio_net_set_config;
> vdc->get_features = virtio_net_get_features;
> @@ -1535,6 +1544,7 @@ static const TypeInfo virtio_net_info = {
> .instance_size = sizeof(VirtIONet),
> .instance_init = virtio_net_instance_init,
> .class_init = virtio_net_class_init,
> + .class_size = sizeof(VirtIONetClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
> index d7a1c33..cacaf64 100644
> --- a/hw/scsi/vhost-scsi.c
> +++ b/hw/scsi/vhost-scsi.c
> @@ -196,29 +196,32 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val)
> }
> }
>
> -static int vhost_scsi_init(VirtIODevice *vdev)
> +static void vhost_scsi_realize(DeviceState *dev, Error **errp)
> {
> - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
> - VHostSCSI *s = VHOST_SCSI(vdev);
> + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
> + VHostSCSI *s = VHOST_SCSI(dev);
> + VHostSCSIClass *vsc = VHOST_SCSI_GET_CLASS(dev);
> + Error *err = NULL;
> int vhostfd = -1;
> int ret;
>
> if (!vs->conf.wwpn) {
> - error_report("vhost-scsi: missing wwpn\n");
> - return -EINVAL;
> + error_setg(errp, "vhost-scsi: missing wwpn");
> + return;
> }
>
> if (vs->conf.vhostfd) {
> vhostfd = monitor_handle_fd_param(cur_mon, vs->conf.vhostfd);
> if (vhostfd == -1) {
> - error_report("vhost-scsi: unable to parse vhostfd\n");
> - return -EINVAL;
> + error_setg(errp, "vhost-scsi: unable to parse vhostfd");
> + return;
> }
> }
>
> - ret = virtio_scsi_common_init(vs);
> - if (ret < 0) {
> - return ret;
> + vsc->parent_realize(dev, &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> }
>
> s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
> @@ -227,24 +230,22 @@ static int vhost_scsi_init(VirtIODevice *vdev)
>
> ret = vhost_dev_init(&s->dev, vhostfd, "/dev/vhost-scsi", true);
> if (ret < 0) {
> - error_report("vhost-scsi: vhost initialization failed: %s\n",
> - strerror(-ret));
> - return ret;
> + error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
> + strerror(-ret));
> + return;
> }
> s->dev.backend_features = 0;
>
> error_setg(&s->migration_blocker,
> "vhost-scsi does not support migration");
> migrate_add_blocker(s->migration_blocker);
> -
> - return 0;
> }
>
> -static int vhost_scsi_exit(DeviceState *qdev)
> +static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> - VHostSCSI *s = VHOST_SCSI(qdev);
> - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VHostSCSI *s = VHOST_SCSI(dev);
> + VHostSCSIClass *vsc = VHOST_SCSI_GET_CLASS(dev);
>
> migrate_del_blocker(s->migration_blocker);
> error_free(s->migration_blocker);
> @@ -253,7 +254,8 @@ static int vhost_scsi_exit(DeviceState *qdev)
> vhost_scsi_set_status(vdev, 0);
>
> g_free(s->dev.vqs);
> - return virtio_scsi_common_exit(vs);
> +
> + vsc->parent_unrealize(dev, errp);
> }
>
> static Property vhost_scsi_properties[] = {
> @@ -261,13 +263,19 @@ static Property vhost_scsi_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void vhost_scsi_class_init(ObjectClass *klass, void *data)
> +static void vhost_scsi_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = vhost_scsi_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VHostSCSIClass *vsc = VHOST_SCSI_CLASS(oc);
> +
> + vsc->parent_realize = dc->realize;
> + dc->realize = vhost_scsi_realize;
> +
> + vsc->parent_unrealize = dc->unrealize;
> + dc->unrealize = vhost_scsi_unrealize;
> +
> dc->props = vhost_scsi_properties;
> - vdc->init = vhost_scsi_init;
> vdc->get_features = vhost_scsi_get_features;
> vdc->set_config = vhost_scsi_set_config;
> vdc->set_status = vhost_scsi_set_status;
> @@ -278,6 +286,7 @@ static const TypeInfo vhost_scsi_info = {
> .parent = TYPE_VIRTIO_SCSI_COMMON,
> .instance_size = sizeof(VHostSCSI),
> .class_init = vhost_scsi_class_init,
> + .class_size = sizeof(VHostSCSIClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 08dd3f3..6704f78 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -587,12 +587,14 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
> .load_request = virtio_scsi_load_request,
> };
>
> -int virtio_scsi_common_init(VirtIOSCSICommon *s)
> +static void virtio_scsi_common_realize(DeviceState *dev, Error **errp)
> {
> - VirtIODevice *vdev = VIRTIO_DEVICE(s);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
> + VirtIOSCSICommonClass *vscc = VIRTIO_SCSI_COMMON_GET_CLASS(dev);
> int i;
>
> - virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
> + virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
> sizeof(VirtIOSCSIConfig));
>
> s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
> @@ -608,50 +610,53 @@ int virtio_scsi_common_init(VirtIOSCSICommon *s)
> virtio_scsi_handle_cmd);
> }
>
> - return 0;
> + vscc->parent_realize(dev, errp);
> }
>
> -static int virtio_scsi_device_init(VirtIODevice *vdev)
> +static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
> {
> - DeviceState *qdev = DEVICE(vdev);
> - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
> - VirtIOSCSI *s = VIRTIO_SCSI(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSCSI *s = VIRTIO_SCSI(dev);
> + VirtIOSCSIClass *vsc = VIRTIO_SCSI_GET_CLASS(dev);
> static int virtio_scsi_id;
> - int ret;
> + Error *err = NULL;
>
> - ret = virtio_scsi_common_init(vs);
> - if (ret < 0) {
> - return ret;
> + vsc->parent_realize(dev, &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> }
>
> - scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, vdev->bus_name);
> + scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info, vdev->bus_name);
>
> - if (!qdev->hotplugged) {
> + if (!dev->hotplugged) {
> scsi_bus_legacy_handle_cmdline(&s->bus);
> }
>
> - register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1,
> + register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
> virtio_scsi_save, virtio_scsi_load, s);
> -
> - return 0;
> }
>
> -int virtio_scsi_common_exit(VirtIOSCSICommon *vs)
> +static void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIODevice *vdev = VIRTIO_DEVICE(vs);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
> + VirtIOSCSICommonClass *vscc = VIRTIO_SCSI_COMMON_GET_CLASS(dev);
>
> g_free(vs->cmd_vqs);
> virtio_cleanup(vdev);
> - return 0;
> +
> + vscc->parent_unrealize(dev, errp);
> }
>
> -static int virtio_scsi_device_exit(DeviceState *qdev)
> +static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIOSCSI *s = VIRTIO_SCSI(qdev);
> - VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
> + VirtIOSCSI *s = VIRTIO_SCSI(dev);
> + VirtIOSCSIClass *vsc = VIRTIO_SCSI_GET_CLASS(dev);
>
> - unregister_savevm(qdev, "virtio-scsi", s);
> - return virtio_scsi_common_exit(vs);
> + unregister_savevm(dev, "virtio-scsi", s);
> +
> + vsc->parent_unrealize(dev, errp);
> }
>
> static Property virtio_scsi_properties[] = {
> @@ -659,20 +664,34 @@ static Property virtio_scsi_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
> +static void virtio_scsi_common_class_init(ObjectClass *oc, void *data)
> {
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIOSCSICommonClass *vscc = VIRTIO_SCSI_COMMON_CLASS(oc);
> +
> + vscc->parent_realize = dc->realize;
> + dc->realize = virtio_scsi_common_realize;
> +
> + vscc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_scsi_common_unrealize;
>
> vdc->get_config = virtio_scsi_get_config;
> }
>
> -static void virtio_scsi_class_init(ObjectClass *klass, void *data)
> +static void virtio_scsi_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_scsi_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIOSCSIClass *vsc = VIRTIO_SCSI_CLASS(oc);
> +
> + vsc->parent_realize = dc->realize;
> + dc->realize = virtio_scsi_device_realize;
> +
> + vsc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_scsi_device_unrealize;
> +
> dc->props = virtio_scsi_properties;
> - vdc->init = virtio_scsi_device_init;
> vdc->set_config = virtio_scsi_set_config;
> vdc->get_features = virtio_scsi_get_features;
> vdc->reset = virtio_scsi_reset;
> @@ -683,6 +702,7 @@ static const TypeInfo virtio_scsi_common_info = {
> .parent = TYPE_VIRTIO_DEVICE,
> .instance_size = sizeof(VirtIOSCSICommon),
> .class_init = virtio_scsi_common_class_init,
> + .class_size = sizeof(VirtIOSCSICommonClass),
> };
>
> static const TypeInfo virtio_scsi_info = {
> @@ -690,6 +710,7 @@ static const TypeInfo virtio_scsi_info = {
> .parent = TYPE_VIRTIO_SCSI_COMMON,
> .instance_size = sizeof(VirtIOSCSI),
> .class_init = virtio_scsi_class_init,
> + .class_size = sizeof(VirtIOSCSIClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
> index d669756..0535062 100644
> --- a/hw/virtio/virtio-balloon.c
> +++ b/hw/virtio/virtio-balloon.c
> @@ -336,10 +336,11 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
> return 0;
> }
>
> -static int virtio_balloon_device_init(VirtIODevice *vdev)
> +static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
> {
> - DeviceState *qdev = DEVICE(vdev);
> - VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOBalloon *s = VIRTIO_BALLOON(dev);
> + VirtIOBalloonClass *vbc = VIRTIO_BALLOON_GET_CLASS(dev);
> int ret;
>
> virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
> @@ -348,50 +349,60 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
> virtio_balloon_stat, s);
>
> if (ret < 0) {
> - virtio_cleanup(VIRTIO_DEVICE(s));
> - return -1;
> + error_setg(errp, "Adding balloon handler failed");
> + virtio_cleanup(vdev);
> + return;
> }
>
> s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
> s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
> s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
>
> - register_savevm(qdev, "virtio-balloon", -1, 1,
> + register_savevm(dev, "virtio-balloon", -1, 1,
> virtio_balloon_save, virtio_balloon_load, s);
>
> - object_property_add(OBJECT(qdev), "guest-stats", "guest statistics",
> + object_property_add(OBJECT(dev), "guest-stats", "guest statistics",
> balloon_stats_get_all, NULL, NULL, s, NULL);
>
> - object_property_add(OBJECT(qdev), "guest-stats-polling-interval", "int",
> + object_property_add(OBJECT(dev), "guest-stats-polling-interval", "int",
> balloon_stats_get_poll_interval,
> balloon_stats_set_poll_interval,
> NULL, s, NULL);
> - return 0;
> +
> + vbc->parent_realize(dev, errp);
> }
>
> -static int virtio_balloon_device_exit(DeviceState *qdev)
> +static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIOBalloon *s = VIRTIO_BALLOON(qdev);
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOBalloon *s = VIRTIO_BALLOON(dev);
> + VirtIOBalloonClass *vbc = VIRTIO_BALLOON_GET_CLASS(dev);
>
> balloon_stats_destroy_timer(s);
> qemu_remove_balloon_handler(s);
> - unregister_savevm(qdev, "virtio-balloon", s);
> + unregister_savevm(dev, "virtio-balloon", s);
> virtio_cleanup(vdev);
> - return 0;
> +
> + vbc->parent_unrealize(dev, errp);
> }
>
> static Property virtio_balloon_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_balloon_class_init(ObjectClass *klass, void *data)
> +static void virtio_balloon_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_balloon_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIOBalloonClass *vbc = VIRTIO_BALLOON_CLASS(oc);
> +
> + vbc->parent_realize = dc->realize;
> + dc->realize = virtio_balloon_device_realize;
> +
> + vbc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_balloon_device_unrealize;
> +
> dc->props = virtio_balloon_properties;
> - vdc->init = virtio_balloon_device_init;
> vdc->get_config = virtio_balloon_get_config;
> vdc->set_config = virtio_balloon_set_config;
> vdc->get_features = virtio_balloon_get_features;
> @@ -402,6 +413,7 @@ static const TypeInfo virtio_balloon_info = {
> .parent = TYPE_VIRTIO_DEVICE,
> .instance_size = sizeof(VirtIOBalloon),
> .class_init = virtio_balloon_class_init,
> + .class_size = sizeof(VirtIOBalloonClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
> index cb787c7..108cfc9 100644
> --- a/hw/virtio/virtio-rng.c
> +++ b/hw/virtio/virtio-rng.c
> @@ -133,21 +133,22 @@ static void check_rate_limit(void *opaque)
> qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
> }
>
> -static int virtio_rng_device_init(VirtIODevice *vdev)
> +static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
> {
> - DeviceState *qdev = DEVICE(vdev);
> - VirtIORNG *vrng = VIRTIO_RNG(vdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIORNG *vrng = VIRTIO_RNG(dev);
> + VirtIORNGClass *vrc = VIRTIO_RNG_GET_CLASS(dev);
> Error *local_err = NULL;
>
> if (vrng->conf.rng == NULL) {
> vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
>
> - object_property_add_child(OBJECT(qdev),
> + object_property_add_child(OBJECT(dev),
> "default-backend",
> OBJECT(vrng->conf.default_backend),
> NULL);
>
> - object_property_set_link(OBJECT(qdev),
> + object_property_set_link(OBJECT(dev),
> OBJECT(vrng->conf.default_backend),
> "rng", NULL);
> }
> @@ -156,15 +157,14 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
>
> vrng->rng = vrng->conf.rng;
> if (vrng->rng == NULL) {
> - qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
> - return -1;
> + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
> + return;
> }
>
> rng_backend_open(vrng->rng, &local_err);
> if (local_err) {
> - qerror_report_err(local_err);
> - error_free(local_err);
> - return -1;
> + error_propagate(errp, local_err);
> + return;
> }
>
> vrng->vq = virtio_add_queue(vdev, 8, handle_input);
> @@ -178,22 +178,24 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
> qemu_mod_timer(vrng->rate_limit_timer,
> qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
>
> - register_savevm(qdev, "virtio-rng", -1, 1, virtio_rng_save,
> + register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
> virtio_rng_load, vrng);
>
> - return 0;
> + vrc->parent_realize(dev, errp);
> }
>
> -static int virtio_rng_device_exit(DeviceState *qdev)
> +static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIORNG *vrng = VIRTIO_RNG(qdev);
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIORNG *vrng = VIRTIO_RNG(dev);
> + VirtIORNGClass *vrc = VIRTIO_RNG_GET_CLASS(dev);
>
> qemu_del_timer(vrng->rate_limit_timer);
> qemu_free_timer(vrng->rate_limit_timer);
> - unregister_savevm(qdev, "virtio-rng", vrng);
> + unregister_savevm(dev, "virtio-rng", vrng);
> virtio_cleanup(vdev);
> - return 0;
> +
> + vrc->parent_unrealize(dev, errp);
> }
>
> static Property virtio_rng_properties[] = {
> @@ -201,13 +203,19 @@ static Property virtio_rng_properties[] = {
> DEFINE_PROP_END_OF_LIST(),
> };
>
> -static void virtio_rng_class_init(ObjectClass *klass, void *data)
> +static void virtio_rng_class_init(ObjectClass *oc, void *data)
> {
> - DeviceClass *dc = DEVICE_CLASS(klass);
> - VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> - dc->exit = virtio_rng_device_exit;
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(oc);
> + VirtIORNGClass *vrc = VIRTIO_RNG_CLASS(oc);
> +
> + vrc->parent_realize = dc->realize;
> + dc->realize = virtio_rng_device_realize;
> +
> + vrc->parent_unrealize = dc->unrealize;
> + dc->unrealize = virtio_rng_device_unrealize;
> +
> dc->props = virtio_rng_properties;
> - vdc->init = virtio_rng_device_init;
> vdc->get_features = get_features;
> }
>
> @@ -225,6 +233,7 @@ static const TypeInfo virtio_rng_info = {
> .instance_size = sizeof(VirtIORNG),
> .instance_init = virtio_rng_initfn,
> .class_init = virtio_rng_class_init,
> + .class_size = sizeof(VirtIORNGClass),
> };
>
> static void virtio_register_types(void)
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 8176c14..d369f9a 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -1105,35 +1105,29 @@ void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
> }
> }
>
> -static int virtio_device_init(DeviceState *qdev)
> +static void virtio_device_realize(DeviceState *dev, Error **errp)
> {
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
> - assert(k->init != NULL);
> - if (k->init(vdev) < 0) {
> - return -1;
> - }
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> +
> virtio_bus_plug_device(vdev);
> - return 0;
> }
>
> -static int virtio_device_exit(DeviceState *qdev)
> +static void virtio_device_unrealize(DeviceState *dev, Error **errp)
> {
> - VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>
> if (vdev->bus_name) {
> g_free(vdev->bus_name);
> vdev->bus_name = NULL;
> }
> - return 0;
> }
>
> static void virtio_device_class_init(ObjectClass *klass, void *data)
> {
> /* Set the default value here. */
> DeviceClass *dc = DEVICE_CLASS(klass);
> - dc->init = virtio_device_init;
> - dc->exit = virtio_device_exit;
> + dc->realize = virtio_device_realize;
> + dc->unrealize = virtio_device_unrealize;
> dc->bus_type = TYPE_VIRTIO_BUS;
> }
>
> diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h
> index 85cc031..b0d64e4 100644
> --- a/include/hw/virtio/vhost-scsi.h
> +++ b/include/hw/virtio/vhost-scsi.h
> @@ -53,6 +53,10 @@ enum vhost_scsi_vq_list {
> #define TYPE_VHOST_SCSI "vhost-scsi"
> #define VHOST_SCSI(obj) \
> OBJECT_CHECK(VHostSCSI, (obj), TYPE_VHOST_SCSI)
> +#define VHOST_SCSI_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VHostSCSIClass, (obj), TYPE_VHOST_SCSI)
> +#define VHOST_SCSI_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VHostSCSIClass, (cls), TYPE_VHOST_SCSI)
>
> typedef struct VHostSCSI {
> VirtIOSCSICommon parent_obj;
> @@ -62,6 +66,15 @@ typedef struct VHostSCSI {
> struct vhost_dev dev;
> } VHostSCSI;
>
> +typedef struct VHostSCSIClass {
> + /*< private >*/
> + VirtIOSCSICommonClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VHostSCSIClass;
> +
> #define DEFINE_VHOST_SCSI_PROPERTIES(_state, _conf_field) \
> DEFINE_PROP_STRING("vhostfd", _state, _conf_field.vhostfd), \
> DEFINE_PROP_STRING("wwpn", _state, _conf_field.wwpn), \
> diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
> index f863bfe..146fa04 100644
> --- a/include/hw/virtio/virtio-balloon.h
> +++ b/include/hw/virtio/virtio-balloon.h
> @@ -21,6 +21,10 @@
> #define TYPE_VIRTIO_BALLOON "virtio-balloon-device"
> #define VIRTIO_BALLOON(obj) \
> OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
> +#define VIRTIO_BALLOON_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIOBalloonClass, (obj), TYPE_VIRTIO_BALLOON)
> +#define VIRTIO_BALLOON_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VirtIOBalloonClass, (cls), TYPE_VIRTIO_BALLOON)
>
> /* from Linux's linux/virtio_balloon.h */
>
> @@ -69,4 +73,13 @@ typedef struct VirtIOBalloon {
> int64_t stats_poll_interval;
> } VirtIOBalloon;
>
> +typedef struct VirtIOBalloonClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIOBalloonClass;
> +
> #endif
> diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
> index fc71853..5ed703d 100644
> --- a/include/hw/virtio/virtio-blk.h
> +++ b/include/hw/virtio/virtio-blk.h
> @@ -20,6 +20,10 @@
> #define TYPE_VIRTIO_BLK "virtio-blk-device"
> #define VIRTIO_BLK(obj) \
> OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK)
> +#define VIRTIO_BLK_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIOBlockClass, (obj), TYPE_VIRTIO_BLK)
> +#define VIRTIO_BLK_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VirtIOBlockClass, (cls), TYPE_VIRTIO_BLK)
>
> /* from Linux's linux/virtio_blk.h */
>
> @@ -129,6 +133,15 @@ typedef struct VirtIOBlock {
> #endif
> } VirtIOBlock;
>
> +typedef struct VirtIOBlockClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIOBlockClass;
> +
> #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
> DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
>
> diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
> index b315ac9..0b8a06e 100644
> --- a/include/hw/virtio/virtio-net.h
> +++ b/include/hw/virtio/virtio-net.h
> @@ -20,6 +20,10 @@
> #define TYPE_VIRTIO_NET "virtio-net-device"
> #define VIRTIO_NET(obj) \
> OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
> +#define VIRTIO_NET_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIONetClass, (obj), TYPE_VIRTIO_NET)
> +#define VIRTIO_NET_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VirtIONetClass, (cls), TYPE_VIRTIO_NET)
>
> #define ETH_ALEN 6
>
> @@ -195,6 +199,15 @@ typedef struct VirtIONet {
> uint64_t curr_guest_offloads;
> } VirtIONet;
>
> +typedef struct VirtIONetClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIONetClass;
> +
> #define VIRTIO_NET_CTRL_MAC 1
> #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
> #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
> diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
> index debaa15..528f70c 100644
> --- a/include/hw/virtio/virtio-rng.h
> +++ b/include/hw/virtio/virtio-rng.h
> @@ -18,6 +18,10 @@
> #define TYPE_VIRTIO_RNG "virtio-rng-device"
> #define VIRTIO_RNG(obj) \
> OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG)
> +#define VIRTIO_RNG_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIORNGClass, (obj), TYPE_VIRTIO_RNG)
> +#define VIRTIO_RNG_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VirtIORNGClass, (cls), TYPE_VIRTIO_RNG)
>
> /* The Virtio ID for the virtio rng device */
> #define VIRTIO_ID_RNG 4
> @@ -46,6 +50,15 @@ typedef struct VirtIORNG {
> int64_t quota_remaining;
> } VirtIORNG;
>
> +typedef struct VirtIORNGClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIORNGClass;
> +
> /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If
> you have an entropy source capable of generating more entropy than this
> and you can pass it through via virtio-rng, then hats off to you. Until
> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> index 9a98540..2ce58cd 100644
> --- a/include/hw/virtio/virtio-scsi.h
> +++ b/include/hw/virtio/virtio-scsi.h
> @@ -21,10 +21,18 @@
> #define TYPE_VIRTIO_SCSI_COMMON "virtio-scsi-common"
> #define VIRTIO_SCSI_COMMON(obj) \
> OBJECT_CHECK(VirtIOSCSICommon, (obj), TYPE_VIRTIO_SCSI_COMMON)
> +#define VIRTIO_SCSI_COMMON_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIOSCSICommonClass, (obj), TYPE_VIRTIO_SCSI_COMMON)
> +#define VIRTIO_SCSI_COMMON_CLASS(cls) \
> + OBJECT_CHECK(VirtIOSCSICommonClass, (cls), TYPE_VIRTIO_SCSI_COMMON)
>
> #define TYPE_VIRTIO_SCSI "virtio-scsi-device"
> #define VIRTIO_SCSI(obj) \
> OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
> +#define VIRTIO_SCSI_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIOSCSIClass, (obj), TYPE_VIRTIO_SCSI)
> +#define VIRTIO_SCSI_CLASS(cls) \
> + OBJECT_CHECK(VirtIOSCSIClass, (cls), TYPE_VIRTIO_SCSI)
>
>
> /* The ID for virtio_scsi */
> @@ -166,6 +174,15 @@ typedef struct VirtIOSCSICommon {
> VirtQueue **cmd_vqs;
> } VirtIOSCSICommon;
>
> +typedef struct VirtIOSCSICommonClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIOSCSICommonClass;
> +
> typedef struct {
> VirtIOSCSICommon parent_obj;
>
> @@ -174,6 +191,15 @@ typedef struct {
> bool events_dropped;
> } VirtIOSCSI;
>
> +typedef struct VirtIOSCSIClass {
> + /*< private >*/
> + VirtIOSCSICommonClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIOSCSIClass;
> +
> #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \
> DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
> DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\
> @@ -186,7 +212,4 @@ typedef struct {
> DEFINE_PROP_BIT("param_change", _state, _feature_field, \
> VIRTIO_SCSI_F_CHANGE, true)
>
> -int virtio_scsi_common_init(VirtIOSCSICommon *vs);
> -int virtio_scsi_common_exit(VirtIOSCSICommon *vs);
> -
> #endif /* _QEMU_VIRTIO_SCSI_H */
> diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h
> index 1d2040b..49af9e3 100644
> --- a/include/hw/virtio/virtio-serial.h
> +++ b/include/hw/virtio/virtio-serial.h
> @@ -212,6 +212,15 @@ struct VirtIOSerial {
> virtio_serial_conf serial;
> };
>
> +typedef struct VirtIOSerialClass {
> + /*< private >*/
> + VirtioDeviceClass parent_class;
> + /*< public >*/
> +
> + DeviceRealize parent_realize;
> + DeviceUnrealize parent_unrealize;
> +} VirtIOSerialClass;
> +
> /* Interface to the virtio-serial bus */
>
> /*
> @@ -247,6 +256,10 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle);
> #define TYPE_VIRTIO_SERIAL "virtio-serial-device"
> #define VIRTIO_SERIAL(obj) \
> OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL)
> +#define VIRTIO_SERIAL_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(VirtIOSerialClass, (obj), TYPE_VIRTIO_SERIAL)
> +#define VIRTIO_SERIAL_CLASS(cls) \
> + OBJECT_CLASS_CHECK(VirtIOSerialClass, (cls), TYPE_VIRTIO_SERIAL)
>
> #define DEFINE_VIRTIO_SERIAL_PROPERTIES(_state, _field) \
> DEFINE_PROP_UINT32("max_ports", _state, _field.max_virtserial_ports, 31)
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index a6c5c53..7e1854a 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -122,9 +122,11 @@ struct VirtIODevice
> };
>
> typedef struct VirtioDeviceClass {
> - /* This is what a VirtioDevice must implement */
> + /*< private >*/
> DeviceClass parent;
> - int (*init)(VirtIODevice *vdev);
> + /*< public >*/
> +
> + /* This is what a VirtioDevice must implement */
> uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
> uint32_t (*bad_features)(VirtIODevice *vdev);
> void (*set_features)(VirtIODevice *vdev, uint32_t val);
> --
> 1.8.1.4
next prev parent reply other threads:[~2013-06-09 10:36 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-07 18:18 [Qemu-devel] [PATCH RFT 0/5] QOM realize for virtio Andreas Färber
2013-06-07 18:18 ` [Qemu-devel] [PATCH RFT 1/5] virtio-blk-dataplane: Improve error reporting Andreas Färber
2013-06-10 11:39 ` Stefan Hajnoczi
2013-07-29 20:19 ` Andreas Färber
2013-06-07 18:18 ` [Qemu-devel] [PATCH RFT 2/5] virtio: Convert VirtioDevice to QOM realize/unrealize Andreas Färber
2013-06-08 2:22 ` Peter Crosthwaite
2013-06-08 9:55 ` Andreas Färber
2013-06-08 12:32 ` Peter Crosthwaite
2013-06-10 2:08 ` Anthony Liguori
2013-06-10 6:30 ` Michael S. Tsirkin
2013-06-12 9:15 ` Andreas Färber
2013-06-13 1:48 ` Peter Crosthwaite
2013-06-18 9:57 ` Peter Crosthwaite
2013-06-09 10:36 ` Michael S. Tsirkin [this message]
2013-06-07 18:18 ` [Qemu-devel] [PATCH RFT 3/5] virtio-console: QOM'ify VirtConsole Andreas Färber
2013-06-07 18:18 ` [Qemu-devel] [PATCH RFT 4/5] virtio-console: Use exitfn for virtserialport, too Andreas Färber
2013-07-29 23:25 ` Andreas Färber
2013-06-07 18:19 ` [Qemu-devel] [PATCH RFT 5/5] virtio-serial-port: Convert to QOM realize/unrealize Andreas Färber
2013-06-09 10:39 ` [Qemu-devel] [PATCH RFT 0/5] QOM realize for virtio Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130609103649.GE14832@redhat.com \
--to=mst@redhat.com \
--cc=afaerber@suse.de \
--cc=aliguori@us.ibm.com \
--cc=amit.shah@redhat.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=anthony@codemonkey.ws \
--cc=fred.konrad@greensocs.com \
--cc=jlarrew@linux.vnet.ibm.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.