From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43922) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ulcz8-00008n-Is for qemu-devel@nongnu.org; Sun, 09 Jun 2013 06:36:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ulcz2-0006oR-Jt for qemu-devel@nongnu.org; Sun, 09 Jun 2013 06:36:30 -0400 Received: from mx1.redhat.com ([209.132.183.28]:1247) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ulcz2-0006oF-5o for qemu-devel@nongnu.org; Sun, 09 Jun 2013 06:36:24 -0400 Date: Sun, 9 Jun 2013 13:36:49 +0300 From: "Michael S. Tsirkin" Message-ID: <20130609103649.GE14832@redhat.com> References: <1370629140-30841-1-git-send-email-afaerber@suse.de> <1370629140-30841-3-git-send-email-afaerber@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <1370629140-30841-3-git-send-email-afaerber@suse.de> Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH RFT 2/5] virtio: Convert VirtioDevice to QOM realize/unrealize List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Andreas =?iso-8859-1?Q?F=E4rber?= Cc: Kevin Wolf , Anthony Liguori , Stefan Hajnoczi , qemu-devel@nongnu.org, jlarrew@linux.vnet.ibm.com, "Aneesh Kumar K.V" , anthony@codemonkey.ws, Amit Shah , Paolo Bonzini , fred.konrad@greensocs.com On Fri, Jun 07, 2013 at 08:18:57PM +0200, Andreas F=E4rber 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. >=20 > 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. >=20 > 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=E4rber > --- > 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(-) >=20 > 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); > } > =20 > -static int virtio_9p_device_init(VirtIODevice *vdev) > +static void virtio_9p_device_realize(DeviceState *dev, Error **errp) > { > - V9fsState *s =3D VIRTIO_9P(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + V9fsState *s =3D VIRTIO_9P(dev); > + V9fsClass *v9c =3D VIRTIO_9P_GET_CLASS(dev); > int i, len; > struct stat stat; > FsDriverEntry *fse; > V9fsPath path; > =20 > - 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); > =20 > /* initialize pdu allocator */ > @@ -65,17 +67,17 @@ static int virtio_9p_device_init(VirtIODevice *vdev= ) > =20 > if (!fse) { > /* We don't have a fsdev identified by fsdev_id */ > - fprintf(stderr, "Virtio-9p device couldn't find fsdev with the= " > - "id =3D %s\n", > - s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); > - return -1; > + error_setg(errp, "Virtio-9p device couldn't find fsdev with th= e " > + "id =3D %s", > + s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); > + return; > } > =20 > 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; > } > =20 > s->ctx.export_flags =3D fse->export_flags; > @@ -83,9 +85,9 @@ static int virtio_9p_device_init(VirtIODevice *vdev) > s->ctx.exops.get_st_gen =3D NULL; > len =3D 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_L= EN - 1); > + return; > } > =20 > s->tag =3D strdup(s->fsconf.tag); > @@ -97,13 +99,13 @@ static int virtio_9p_device_init(VirtIODevice *vdev= ) > qemu_co_rwlock_init(&s->rename_lock); > =20 > 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 wit= h id:%s" > + " and export path:%s", s->fsconf.fsdev_id, s->ctx.f= s_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; > } > =20 > /* > @@ -113,20 +115,20 @@ static int virtio_9p_device_init(VirtIODevice *vd= ev) > */ > 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(err= no)); > + 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->pat= h); > - return -1; > + error_setg(errp, "share path %s is not a directory", fse->path= ); > + return; > } > v9fs_path_free(&path); > =20 > - return 0; > + v9c->parent_realize(dev, errp); > } > =20 > /* virtio-9p device */ > @@ -136,12 +138,16 @@ static Property virtio_9p_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_9p_class_init(ObjectClass *klass, void *data) > +static void virtio_9p_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + V9fsClass *v9c =3D VIRTIO_9P_CLASS(oc); > + > + v9c->parent_realize =3D dc->realize; > + dc->realize =3D virtio_9p_device_realize; > + > dc->props =3D virtio_9p_properties; > - vdc->init =3D virtio_9p_device_init; > vdc->get_features =3D virtio_9p_get_features; > vdc->get_config =3D virtio_9p_get_config; > } > @@ -151,6 +157,7 @@ static const TypeInfo virtio_device_info =3D { > .parent =3D TYPE_VIRTIO_DEVICE, > .instance_size =3D sizeof(V9fsState), > .class_init =3D virtio_9p_class_init, > + .class_size =3D sizeof(V9fsClass), > }; > =20 > 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; > =20 > +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, V9fsPat= h *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) > =20 > #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, VirtIO= BlkConf *blk) > memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf)); > } > =20 > -static int virtio_blk_device_init(VirtIODevice *vdev) > +static void virtio_blk_device_realize(DeviceState *dev, Error **errp) > { > - DeviceState *qdev =3D DEVICE(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > VirtIOBlock *s =3D VIRTIO_BLK(vdev); > + VirtIOBlockClass *vbc =3D VIRTIO_BLK_GET_CLASS(dev); > VirtIOBlkConf *blk =3D &(s->blk); > #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE > Error *err =3D NULL; > @@ -639,17 +640,18 @@ static int virtio_blk_device_init(VirtIODevice *v= dev) > static int virtio_blk_id; > =20 > 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; > } > =20 > 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; > } > =20 > virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, > @@ -665,29 +667,31 @@ static int virtio_blk_device_init(VirtIODevice *v= dev) > #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE > virtio_blk_data_plane_create(vdev, blk, &s->dataplane, &err); > if (err !=3D NULL) { > - error_report("%s", error_get_pretty(err)); > - error_free(err); > + error_propagate(errp, err); > virtio_cleanup(vdev); > - return -1; > + return; > } > #endif > =20 > s->change =3D qemu_add_vm_change_state_handler(virtio_blk_dma_rest= art_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); > =20 > bdrv_iostatus_enable(s->bs); > =20 > - 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); > } > =20 > -static int virtio_blk_device_exit(DeviceState *dev) > +static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp= ) > { > VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > VirtIOBlock *s =3D VIRTIO_BLK(dev); > + VirtIOBlockClass *vbc =3D VIRTIO_BLK_GET_CLASS(dev); > + > #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE > virtio_blk_data_plane_destroy(s->dataplane); > s->dataplane =3D 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); > } > =20 > static Property virtio_blk_properties[] =3D { > @@ -704,13 +709,19 @@ static Property virtio_blk_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_blk_class_init(ObjectClass *klass, void *data) > +static void virtio_blk_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_blk_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIOBlockClass *vbc =3D VIRTIO_BLK_CLASS(oc); > + > + vbc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_blk_device_realize; > + > + vbc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_blk_device_unrealize; > + > dc->props =3D virtio_blk_properties; > - vdc->init =3D virtio_blk_device_init; > vdc->get_config =3D virtio_blk_update_config; > vdc->set_config =3D virtio_blk_set_config; > vdc->get_features =3D virtio_blk_get_features; > @@ -723,6 +734,7 @@ static const TypeInfo virtio_device_info =3D { > .parent =3D TYPE_VIRTIO_DEVICE, > .instance_size =3D sizeof(VirtIOBlock), > .class_init =3D virtio_blk_class_init, > + .class_size =3D sizeof(VirtIOBlockClass), > }; > =20 > 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 *qd= ev) > return 0; > } > =20 > -static int virtio_serial_device_init(VirtIODevice *vdev) > +static void virtio_serial_device_realize(DeviceState *dev, Error **err= p) > { > - DeviceState *qdev =3D DEVICE(vdev); > - VirtIOSerial *vser =3D VIRTIO_SERIAL(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOSerial *vser =3D VIRTIO_SERIAL(dev); > + VirtIOSerialClass *vsc =3D VIRTIO_SERIAL_GET_CLASS(dev); > + BusState *bus; > uint32_t i, max_supported_ports; > =20 > if (!vser->serial.max_virtserial_ports) { > - return -1; > + error_setg(errp, "Maximum number of serial ports not specified= "); > + return; > } > =20 > /* Each port takes 2 queues, and one pair is for the control queue= */ > max_supported_ports =3D VIRTIO_PCI_QUEUE_MAX / 2 - 1; > =20 > if (vser->serial.max_virtserial_ports > max_supported_ports) { > - error_report("maximum ports supported: %u", max_supported_port= s); > - return -1; > + error_setg(errp, "maximum ports supported: %u", max_supported_= ports); > + return; > } > =20 > virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE, > sizeof(struct virtio_console_config)); > =20 > /* Spawn a new virtio-serial bus on which the ports will ride as d= evices */ > - 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 =3D 1; > + bus =3D BUS(&vser->bus); > + bus->allow_hotplug =3D 1; > vser->bus.vser =3D vser; > QTAILQ_INIT(&vser->ports); > =20 > @@ -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); > =20 > - return 0; > + vsc->parent_realize(dev, errp); > } > =20 > static void virtio_serial_port_class_init(ObjectClass *klass, void *da= ta) > @@ -986,10 +990,11 @@ static const TypeInfo virtio_serial_port_type_inf= o =3D { > .class_init =3D virtio_serial_port_class_init, > }; > =20 > -static int virtio_serial_device_exit(DeviceState *dev) > +static void virtio_serial_device_unrealize(DeviceState *dev, Error **e= rrp) > { > - VirtIOSerial *vser =3D VIRTIO_SERIAL(dev); > VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOSerial *vser =3D VIRTIO_SERIAL(dev); > + VirtIOSerialClass *vsc =3D VIRTIO_SERIAL_GET_CLASS(dev); > =20 > unregister_savevm(dev, "virtio-console", vser); > =20 > @@ -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); > } > =20 > static Property virtio_serial_properties[] =3D { > @@ -1011,13 +1017,19 @@ static Property virtio_serial_properties[] =3D = { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_serial_class_init(ObjectClass *klass, void *data) > +static void virtio_serial_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_serial_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIOSerialClass *vsc =3D VIRTIO_SERIAL_CLASS(oc); > + > + vsc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_serial_device_realize; > + > + vsc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_serial_device_unrealize; > + > dc->props =3D virtio_serial_properties; > - vdc->init =3D virtio_serial_device_init; > vdc->get_features =3D get_features; > vdc->get_config =3D get_config; > vdc->set_config =3D set_config; > @@ -1030,6 +1042,7 @@ static const TypeInfo virtio_device_info =3D { > .parent =3D TYPE_VIRTIO_DEVICE, > .instance_size =3D sizeof(VirtIOSerial), > .class_init =3D virtio_serial_class_init, > + .class_size =3D sizeof(VirtIOSerialClass), > }; > =20 > 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 =3D g_strdup(type); > } > =20 > -static int virtio_net_device_init(VirtIODevice *vdev) > +static void virtio_net_device_realize(DeviceState *dev, Error **errp) > { > int i; > =20 > - DeviceState *qdev =3D DEVICE(vdev); > - VirtIONet *n =3D VIRTIO_NET(vdev); > + DeviceState *qdev =3D DEVICE(dev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIONet *n =3D VIRTIO_NET(dev); > + VirtIONetClass *vnc =3D VIRTIO_NET_GET_CLASS(dev); > =20 > - virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET, > - n->config_size); > + virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); > =20 > n->max_queues =3D MAX(n->nic_conf.queues, 1); > n->vqs =3D g_malloc0(sizeof(VirtIONetQueue) * n->max_queues); > @@ -1439,24 +1440,26 @@ static int virtio_net_device_init(VirtIODevice = *vdev) > =20 > n->vlans =3D g_malloc0(MAX_VLAN >> 3); > =20 > - n->qdev =3D qdev; > - register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, > + n->qdev =3D dev; > + register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, > virtio_net_save, virtio_net_load, n); > =20 > - 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); > } > =20 > -static int virtio_net_device_exit(DeviceState *qdev) > +static void virtio_net_device_unrealize(DeviceState *dev, Error **errp= ) > { > - VirtIONet *n =3D VIRTIO_NET(qdev); > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIONet *n =3D VIRTIO_NET(dev); > + VirtIONetClass *vnc =3D VIRTIO_NET_GET_CLASS(dev); > int i; > =20 > /* This will stop vhost backend if appropriate. */ > virtio_net_set_status(vdev, 0); > =20 > - unregister_savevm(qdev, "virtio-net", n); > + unregister_savevm(dev, "virtio-net", n); > =20 > if (n->netclient_name) { > g_free(n->netclient_name); > @@ -1488,7 +1491,7 @@ static int virtio_net_device_exit(DeviceState *qd= ev) > qemu_del_nic(n->nic); > virtio_cleanup(vdev); > =20 > - return 0; > + vnc->parent_unrealize(dev, errp); > } > =20 > static void virtio_net_instance_init(Object *obj) > @@ -1511,13 +1514,19 @@ static Property virtio_net_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_net_class_init(ObjectClass *klass, void *data) > +static void virtio_net_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_net_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIONetClass *vnc =3D VIRTIO_NET_CLASS(oc); > + > + vnc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_net_device_realize; > + > + vnc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_net_device_unrealize; > + > dc->props =3D virtio_net_properties; > - vdc->init =3D virtio_net_device_init; > vdc->get_config =3D virtio_net_get_config; > vdc->set_config =3D virtio_net_set_config; > vdc->get_features =3D virtio_net_get_features; > @@ -1535,6 +1544,7 @@ static const TypeInfo virtio_net_info =3D { > .instance_size =3D sizeof(VirtIONet), > .instance_init =3D virtio_net_instance_init, > .class_init =3D virtio_net_class_init, > + .class_size =3D sizeof(VirtIONetClass), > }; > =20 > 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 *v= dev, uint8_t val) > } > } > =20 > -static int vhost_scsi_init(VirtIODevice *vdev) > +static void vhost_scsi_realize(DeviceState *dev, Error **errp) > { > - VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(vdev); > - VHostSCSI *s =3D VHOST_SCSI(vdev); > + VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(dev); > + VHostSCSI *s =3D VHOST_SCSI(dev); > + VHostSCSIClass *vsc =3D VHOST_SCSI_GET_CLASS(dev); > + Error *err =3D NULL; > int vhostfd =3D -1; > int ret; > =20 > if (!vs->conf.wwpn) { > - error_report("vhost-scsi: missing wwpn\n"); > - return -EINVAL; > + error_setg(errp, "vhost-scsi: missing wwpn"); > + return; > } > =20 > if (vs->conf.vhostfd) { > vhostfd =3D monitor_handle_fd_param(cur_mon, vs->conf.vhostfd)= ; > if (vhostfd =3D=3D -1) { > - error_report("vhost-scsi: unable to parse vhostfd\n"); > - return -EINVAL; > + error_setg(errp, "vhost-scsi: unable to parse vhostfd"); > + return; > } > } > =20 > - ret =3D virtio_scsi_common_init(vs); > - if (ret < 0) { > - return ret; > + vsc->parent_realize(dev, &err); > + if (err !=3D NULL) { > + error_propagate(errp, err); > + return; > } > =20 > s->dev.nvqs =3D VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; > @@ -227,24 +230,22 @@ static int vhost_scsi_init(VirtIODevice *vdev) > =20 > ret =3D 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 =3D 0; > =20 > error_setg(&s->migration_blocker, > "vhost-scsi does not support migration"); > migrate_add_blocker(s->migration_blocker); > - > - return 0; > } > =20 > -static int vhost_scsi_exit(DeviceState *qdev) > +static void vhost_scsi_unrealize(DeviceState *dev, Error **errp) > { > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > - VHostSCSI *s =3D VHOST_SCSI(qdev); > - VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(qdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VHostSCSI *s =3D VHOST_SCSI(dev); > + VHostSCSIClass *vsc =3D VHOST_SCSI_GET_CLASS(dev); > =20 > 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); > =20 > g_free(s->dev.vqs); > - return virtio_scsi_common_exit(vs); > + > + vsc->parent_unrealize(dev, errp); > } > =20 > static Property vhost_scsi_properties[] =3D { > @@ -261,13 +263,19 @@ static Property vhost_scsi_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void vhost_scsi_class_init(ObjectClass *klass, void *data) > +static void vhost_scsi_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D vhost_scsi_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VHostSCSIClass *vsc =3D VHOST_SCSI_CLASS(oc); > + > + vsc->parent_realize =3D dc->realize; > + dc->realize =3D vhost_scsi_realize; > + > + vsc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D vhost_scsi_unrealize; > + > dc->props =3D vhost_scsi_properties; > - vdc->init =3D vhost_scsi_init; > vdc->get_features =3D vhost_scsi_get_features; > vdc->set_config =3D vhost_scsi_set_config; > vdc->set_status =3D vhost_scsi_set_status; > @@ -278,6 +286,7 @@ static const TypeInfo vhost_scsi_info =3D { > .parent =3D TYPE_VIRTIO_SCSI_COMMON, > .instance_size =3D sizeof(VHostSCSI), > .class_init =3D vhost_scsi_class_init, > + .class_size =3D sizeof(VHostSCSIClass), > }; > =20 > 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 =3D= { > .load_request =3D virtio_scsi_load_request, > }; > =20 > -int virtio_scsi_common_init(VirtIOSCSICommon *s) > +static void virtio_scsi_common_realize(DeviceState *dev, Error **errp) > { > - VirtIODevice *vdev =3D VIRTIO_DEVICE(s); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOSCSICommon *s =3D VIRTIO_SCSI_COMMON(dev); > + VirtIOSCSICommonClass *vscc =3D VIRTIO_SCSI_COMMON_GET_CLASS(dev); > int i; > =20 > - virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI, > + virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI, > sizeof(VirtIOSCSIConfig)); > =20 > s->cmd_vqs =3D g_malloc0(s->conf.num_queues * sizeof(VirtQueue *))= ; > @@ -608,50 +610,53 @@ int virtio_scsi_common_init(VirtIOSCSICommon *s) > virtio_scsi_handle_cmd); > } > =20 > - return 0; > + vscc->parent_realize(dev, errp); > } > =20 > -static int virtio_scsi_device_init(VirtIODevice *vdev) > +static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) > { > - DeviceState *qdev =3D DEVICE(vdev); > - VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(vdev); > - VirtIOSCSI *s =3D VIRTIO_SCSI(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOSCSI *s =3D VIRTIO_SCSI(dev); > + VirtIOSCSIClass *vsc =3D VIRTIO_SCSI_GET_CLASS(dev); > static int virtio_scsi_id; > - int ret; > + Error *err =3D NULL; > =20 > - ret =3D virtio_scsi_common_init(vs); > - if (ret < 0) { > - return ret; > + vsc->parent_realize(dev, &err); > + if (err !=3D NULL) { > + error_propagate(errp, err); > + return; > } > =20 > - 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)= ; > =20 > - if (!qdev->hotplugged) { > + if (!dev->hotplugged) { > scsi_bus_legacy_handle_cmdline(&s->bus); > } > =20 > - 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; > } > =20 > -int virtio_scsi_common_exit(VirtIOSCSICommon *vs) > +static void virtio_scsi_common_unrealize(DeviceState *dev, Error **err= p) > { > - VirtIODevice *vdev =3D VIRTIO_DEVICE(vs); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(dev); > + VirtIOSCSICommonClass *vscc =3D VIRTIO_SCSI_COMMON_GET_CLASS(dev); > =20 > g_free(vs->cmd_vqs); > virtio_cleanup(vdev); > - return 0; > + > + vscc->parent_unrealize(dev, errp); > } > =20 > -static int virtio_scsi_device_exit(DeviceState *qdev) > +static void virtio_scsi_device_unrealize(DeviceState *dev, Error **err= p) > { > - VirtIOSCSI *s =3D VIRTIO_SCSI(qdev); > - VirtIOSCSICommon *vs =3D VIRTIO_SCSI_COMMON(qdev); > + VirtIOSCSI *s =3D VIRTIO_SCSI(dev); > + VirtIOSCSIClass *vsc =3D VIRTIO_SCSI_GET_CLASS(dev); > =20 > - unregister_savevm(qdev, "virtio-scsi", s); > - return virtio_scsi_common_exit(vs); > + unregister_savevm(dev, "virtio-scsi", s); > + > + vsc->parent_unrealize(dev, errp); > } > =20 > static Property virtio_scsi_properties[] =3D { > @@ -659,20 +664,34 @@ static Property virtio_scsi_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_scsi_common_class_init(ObjectClass *klass, void *da= ta) > +static void virtio_scsi_common_class_init(ObjectClass *oc, void *data) > { > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIOSCSICommonClass *vscc =3D VIRTIO_SCSI_COMMON_CLASS(oc); > + > + vscc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_scsi_common_realize; > + > + vscc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_scsi_common_unrealize; > =20 > vdc->get_config =3D virtio_scsi_get_config; > } > =20 > -static void virtio_scsi_class_init(ObjectClass *klass, void *data) > +static void virtio_scsi_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_scsi_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIOSCSIClass *vsc =3D VIRTIO_SCSI_CLASS(oc); > + > + vsc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_scsi_device_realize; > + > + vsc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_scsi_device_unrealize; > + > dc->props =3D virtio_scsi_properties; > - vdc->init =3D virtio_scsi_device_init; > vdc->set_config =3D virtio_scsi_set_config; > vdc->get_features =3D virtio_scsi_get_features; > vdc->reset =3D virtio_scsi_reset; > @@ -683,6 +702,7 @@ static const TypeInfo virtio_scsi_common_info =3D { > .parent =3D TYPE_VIRTIO_DEVICE, > .instance_size =3D sizeof(VirtIOSCSICommon), > .class_init =3D virtio_scsi_common_class_init, > + .class_size =3D sizeof(VirtIOSCSICommonClass), > }; > =20 > static const TypeInfo virtio_scsi_info =3D { > @@ -690,6 +710,7 @@ static const TypeInfo virtio_scsi_info =3D { > .parent =3D TYPE_VIRTIO_SCSI_COMMON, > .instance_size =3D sizeof(VirtIOSCSI), > .class_init =3D virtio_scsi_class_init, > + .class_size =3D sizeof(VirtIOSCSIClass), > }; > =20 > 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; > } > =20 > -static int virtio_balloon_device_init(VirtIODevice *vdev) > +static void virtio_balloon_device_realize(DeviceState *dev, Error **er= rp) > { > - DeviceState *qdev =3D DEVICE(vdev); > - VirtIOBalloon *s =3D VIRTIO_BALLOON(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOBalloon *s =3D VIRTIO_BALLOON(dev); > + VirtIOBalloonClass *vbc =3D VIRTIO_BALLOON_GET_CLASS(dev); > int ret; > =20 > virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8); > @@ -348,50 +349,60 @@ static int virtio_balloon_device_init(VirtIODevic= e *vdev) > virtio_balloon_stat, s); > =20 > if (ret < 0) { > - virtio_cleanup(VIRTIO_DEVICE(s)); > - return -1; > + error_setg(errp, "Adding balloon handler failed"); > + virtio_cleanup(vdev); > + return; > } > =20 > s->ivq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_outpu= t); > s->dvq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_outpu= t); > s->svq =3D virtio_add_queue(vdev, 128, virtio_balloon_receive_stat= s); > =20 > - register_savevm(qdev, "virtio-balloon", -1, 1, > + register_savevm(dev, "virtio-balloon", -1, 1, > virtio_balloon_save, virtio_balloon_load, s); > =20 > - 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); > =20 > - 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); > } > =20 > -static int virtio_balloon_device_exit(DeviceState *qdev) > +static void virtio_balloon_device_unrealize(DeviceState *dev, Error **= errp) > { > - VirtIOBalloon *s =3D VIRTIO_BALLOON(qdev); > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIOBalloon *s =3D VIRTIO_BALLOON(dev); > + VirtIOBalloonClass *vbc =3D VIRTIO_BALLOON_GET_CLASS(dev); > =20 > 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); > } > =20 > static Property virtio_balloon_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_balloon_class_init(ObjectClass *klass, void *data) > +static void virtio_balloon_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_balloon_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIOBalloonClass *vbc =3D VIRTIO_BALLOON_CLASS(oc); > + > + vbc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_balloon_device_realize; > + > + vbc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_balloon_device_unrealize; > + > dc->props =3D virtio_balloon_properties; > - vdc->init =3D virtio_balloon_device_init; > vdc->get_config =3D virtio_balloon_get_config; > vdc->set_config =3D virtio_balloon_set_config; > vdc->get_features =3D virtio_balloon_get_features; > @@ -402,6 +413,7 @@ static const TypeInfo virtio_balloon_info =3D { > .parent =3D TYPE_VIRTIO_DEVICE, > .instance_size =3D sizeof(VirtIOBalloon), > .class_init =3D virtio_balloon_class_init, > + .class_size =3D sizeof(VirtIOBalloonClass), > }; > =20 > 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)= ; > } > =20 > -static int virtio_rng_device_init(VirtIODevice *vdev) > +static void virtio_rng_device_realize(DeviceState *dev, Error **errp) > { > - DeviceState *qdev =3D DEVICE(vdev); > - VirtIORNG *vrng =3D VIRTIO_RNG(vdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIORNG *vrng =3D VIRTIO_RNG(dev); > + VirtIORNGClass *vrc =3D VIRTIO_RNG_GET_CLASS(dev); > Error *local_err =3D NULL; > =20 > if (vrng->conf.rng =3D=3D NULL) { > vrng->conf.default_backend =3D RNG_RANDOM(object_new(TYPE_RNG_= RANDOM)); > =20 > - object_property_add_child(OBJECT(qdev), > + object_property_add_child(OBJECT(dev), > "default-backend", > OBJECT(vrng->conf.default_backend), > NULL); > =20 > - 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 *v= dev) > =20 > vrng->rng =3D vrng->conf.rng; > if (vrng->rng =3D=3D NULL) { > - qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid ob= ject"); > - return -1; > + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "rng", "a valid = object"); > + return; > } > =20 > 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; > } > =20 > vrng->vq =3D virtio_add_queue(vdev, 8, handle_input); > @@ -178,22 +178,24 @@ static int virtio_rng_device_init(VirtIODevice *v= dev) > qemu_mod_timer(vrng->rate_limit_timer, > qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms)= ; > =20 > - register_savevm(qdev, "virtio-rng", -1, 1, virtio_rng_save, > + register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save, > virtio_rng_load, vrng); > =20 > - return 0; > + vrc->parent_realize(dev, errp); > } > =20 > -static int virtio_rng_device_exit(DeviceState *qdev) > +static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp= ) > { > - VirtIORNG *vrng =3D VIRTIO_RNG(qdev); > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIORNG *vrng =3D VIRTIO_RNG(dev); > + VirtIORNGClass *vrc =3D VIRTIO_RNG_GET_CLASS(dev); > =20 > 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); > } > =20 > static Property virtio_rng_properties[] =3D { > @@ -201,13 +203,19 @@ static Property virtio_rng_properties[] =3D { > DEFINE_PROP_END_OF_LIST(), > }; > =20 > -static void virtio_rng_class_init(ObjectClass *klass, void *data) > +static void virtio_rng_class_init(ObjectClass *oc, void *data) > { > - DeviceClass *dc =3D DEVICE_CLASS(klass); > - VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(klass); > - dc->exit =3D virtio_rng_device_exit; > + DeviceClass *dc =3D DEVICE_CLASS(oc); > + VirtioDeviceClass *vdc =3D VIRTIO_DEVICE_CLASS(oc); > + VirtIORNGClass *vrc =3D VIRTIO_RNG_CLASS(oc); > + > + vrc->parent_realize =3D dc->realize; > + dc->realize =3D virtio_rng_device_realize; > + > + vrc->parent_unrealize =3D dc->unrealize; > + dc->unrealize =3D virtio_rng_device_unrealize; > + > dc->props =3D virtio_rng_properties; > - vdc->init =3D virtio_rng_device_init; > vdc->get_features =3D get_features; > } > =20 > @@ -225,6 +233,7 @@ static const TypeInfo virtio_rng_info =3D { > .instance_size =3D sizeof(VirtIORNG), > .instance_init =3D virtio_rng_initfn, > .class_init =3D virtio_rng_class_init, > + .class_size =3D sizeof(VirtIORNGClass), > }; > =20 > 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(VirtIODev= ice *vdev, char *bus_name) > } > } > =20 > -static int virtio_device_init(DeviceState *qdev) > +static void virtio_device_realize(DeviceState *dev, Error **errp) > { > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > - VirtioDeviceClass *k =3D VIRTIO_DEVICE_GET_CLASS(qdev); > - assert(k->init !=3D NULL); > - if (k->init(vdev) < 0) { > - return -1; > - } > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + > virtio_bus_plug_device(vdev); > - return 0; > } > =20 > -static int virtio_device_exit(DeviceState *qdev) > +static void virtio_device_unrealize(DeviceState *dev, Error **errp) > { > - VirtIODevice *vdev =3D VIRTIO_DEVICE(qdev); > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > =20 > if (vdev->bus_name) { > g_free(vdev->bus_name); > vdev->bus_name =3D NULL; > } > - return 0; > } > =20 > static void virtio_device_class_init(ObjectClass *klass, void *data) > { > /* Set the default value here. */ > DeviceClass *dc =3D DEVICE_CLASS(klass); > - dc->init =3D virtio_device_init; > - dc->exit =3D virtio_device_exit; > + dc->realize =3D virtio_device_realize; > + dc->unrealize =3D virtio_device_unrealize; > dc->bus_type =3D TYPE_VIRTIO_BUS; > } > =20 > diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-s= csi.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) > =20 > typedef struct VHostSCSI { > VirtIOSCSICommon parent_obj; > @@ -62,6 +66,15 @@ typedef struct VHostSCSI { > struct vhost_dev dev; > } VHostSCSI; > =20 > +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/vir= tio-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_BALLOO= N) > +#define VIRTIO_BALLOON_CLASS(cls) \ > + OBJECT_CLASS_CHECK(VirtIOBalloonClass, (cls), TYPE_VIRTIO_BALL= OON) > =20 > /* from Linux's linux/virtio_balloon.h */ > =20 > @@ -69,4 +73,13 @@ typedef struct VirtIOBalloon { > int64_t stats_poll_interval; > } VirtIOBalloon; > =20 > +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) > =20 > /* from Linux's linux/virtio_blk.h */ > =20 > @@ -129,6 +133,15 @@ typedef struct VirtIOBlock { > #endif > } VirtIOBlock; > =20 > +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) > =20 > 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) > =20 > #define ETH_ALEN 6 > =20 > @@ -195,6 +199,15 @@ typedef struct VirtIONet { > uint64_t curr_guest_offloads; > } VirtIONet; > =20 > +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) > =20 > /* 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; > =20 > +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_SCS= I_COMMON) > +#define VIRTIO_SCSI_COMMON_CLASS(cls) \ > + OBJECT_CHECK(VirtIOSCSICommonClass, (cls), TYPE_VIRTIO_SCSI_CO= MMON) > =20 > #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) > =20 > =20 > /* The ID for virtio_scsi */ > @@ -166,6 +174,15 @@ typedef struct VirtIOSCSICommon { > VirtQueue **cmd_vqs; > } VirtIOSCSICommon; > =20 > +typedef struct VirtIOSCSICommonClass { > + /*< private >*/ > + VirtioDeviceClass parent_class; > + /*< public >*/ > + > + DeviceRealize parent_realize; > + DeviceUnrealize parent_unrealize; > +} VirtIOSCSICommonClass; > + > typedef struct { > VirtIOSCSICommon parent_obj; > =20 > @@ -174,6 +191,15 @@ typedef struct { > bool events_dropped; > } VirtIOSCSI; > =20 > +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= ) > =20 > -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/virt= io-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; > }; > =20 > +typedef struct VirtIOSerialClass { > + /*< private >*/ > + VirtioDeviceClass parent_class; > + /*< public >*/ > + > + DeviceRealize parent_realize; > + DeviceUnrealize parent_unrealize; > +} VirtIOSerialClass; > + > /* Interface to the virtio-serial bus */ > =20 > /* > @@ -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_SERIA= L) > =20 > #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 > }; > =20 > 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_fe= atures); > uint32_t (*bad_features)(VirtIODevice *vdev); > void (*set_features)(VirtIODevice *vdev, uint32_t val); > --=20 > 1.8.1.4