Patchwork [08/13] qdev: Decouple qdev_prop_drive from DriveInfo

login
register
mail settings
Submitter Markus Armbruster
Date June 2, 2010, 4:55 p.m.
Message ID <1275497729-13120-9-git-send-email-armbru@redhat.com>
Download mbox | patch
Permalink /patch/54404/
State New
Headers show

Comments

Markus Armbruster - June 2, 2010, 4:55 p.m.
Make the property point to BlockDriverState, cutting out the DriveInfo
middleman.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block_int.h          |    6 ++----
 hw/fdc.c             |   22 ++++++++++------------
 hw/ide/core.c        |   14 +++++++-------
 hw/ide/internal.h    |    2 +-
 hw/ide/qdev.c        |    8 ++++----
 hw/pci-hotplug.c     |    4 ++--
 hw/qdev-properties.c |   39 ++++++++++++++++++++++++++++++++-------
 hw/qdev.h            |    6 +++---
 hw/s390-virtio.c     |    2 +-
 hw/scsi-bus.c        |    8 ++++----
 hw/scsi-disk.c       |   16 ++++++++--------
 hw/scsi-generic.c    |    5 ++---
 hw/scsi.h            |    2 +-
 hw/usb-msd.c         |   10 +++++-----
 hw/virtio-blk.c      |    2 +-
 hw/virtio-pci.c      |   12 ++----------
 16 files changed, 85 insertions(+), 73 deletions(-)
Gerd Hoffmann - June 2, 2010, 7:28 p.m.
Hi,

> +static void free_drive(DeviceState *dev, Property *prop)
> +{
> +    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
> +
> +    if (*ptr) {
> +        blockdev_detach(*ptr, dev);
> +    }
> +}

> @@ -1043,26 +1043,26 @@ static void scsi_destroy(SCSIDevice *dev)
>       SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
>
>       scsi_disk_purge_requests(s);
> -    drive_uninit(s->qdev.conf.dinfo);
>   }

Neat.  Commit message should better explain that though.

cheers,
   Gerd
Markus Armbruster - June 4, 2010, 8:22 a.m.
Gerd Hoffmann <kraxel@redhat.com> writes:

>   Hi,
>
>> +static void free_drive(DeviceState *dev, Property *prop)
>> +{
>> +    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
>> +
>> +    if (*ptr) {
>> +        blockdev_detach(*ptr, dev);
>> +    }
>> +}
>
>> @@ -1043,26 +1043,26 @@ static void scsi_destroy(SCSIDevice *dev)
>>       SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
>>
>>       scsi_disk_purge_requests(s);
>> -    drive_uninit(s->qdev.conf.dinfo);
>>   }
>
> Neat.  Commit message should better explain that though.

Point.  I'll try to improve it.

Patch

diff --git a/block_int.h b/block_int.h
index e3bfd19..545b494 100644
--- a/block_int.h
+++ b/block_int.h
@@ -210,10 +210,8 @@  void *qemu_blockalign(BlockDriverState *bs, size_t size);
 int is_windows_drive(const char *filename);
 #endif
 
-struct DriveInfo;
-
 typedef struct BlockConf {
-    struct DriveInfo *dinfo;
+    BlockDriverState *bs;
     uint16_t physical_block_size;
     uint16_t logical_block_size;
     uint16_t min_io_size;
@@ -232,7 +230,7 @@  static inline unsigned int get_physical_block_exp(BlockConf *conf)
 }
 
 #define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
-    DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo),                    \
+    DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
     DEFINE_PROP_UINT16("logical_block_size", _state,                    \
                        _conf.logical_block_size, 512),                  \
     DEFINE_PROP_UINT16("physical_block_size", _state,                   \
diff --git a/hw/fdc.c b/hw/fdc.c
index b978957..2b3cbb9 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -80,7 +80,6 @@  typedef enum FDiskFlags {
 } FDiskFlags;
 
 typedef struct FDrive {
-    DriveInfo *dinfo;
     BlockDriverState *bs;
     /* Drive status */
     FDriveType drive;
@@ -100,7 +99,6 @@  typedef struct FDrive {
 static void fd_init(FDrive *drv)
 {
     /* Drive */
-    drv->bs = drv->dinfo ? drv->dinfo->bdrv : NULL;
     drv->drive = FDRIVE_DRV_NONE;
     drv->perpendicular = 0;
     /* Disk */
@@ -1862,10 +1860,10 @@  FDCtrl *fdctrl_init_isa(DriveInfo **fds)
 
     dev = isa_create("isa-fdc");
     if (fds[0]) {
-        qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]);
+        qdev_prop_set_drive(&dev->qdev, "driveA", fds[0]->bdrv);
     }
     if (fds[1]) {
-        qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]);
+        qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]->bdrv);
     }
     if (qdev_init(&dev->qdev) < 0)
         return NULL;
@@ -1884,10 +1882,10 @@  FDCtrl *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
     fdctrl = &sys->state;
     fdctrl->dma_chann = dma_chann; /* FIXME */
     if (fds[0]) {
-        qdev_prop_set_drive(dev, "driveA", fds[0]);
+        qdev_prop_set_drive(dev, "driveA", fds[0]->bdrv);
     }
     if (fds[1]) {
-        qdev_prop_set_drive(dev, "driveB", fds[1]);
+        qdev_prop_set_drive(dev, "driveB", fds[1]->bdrv);
     }
     qdev_init_nofail(dev);
     sysbus_connect_irq(&sys->busdev, 0, irq);
@@ -1905,7 +1903,7 @@  FDCtrl *sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
 
     dev = qdev_create(NULL, "SUNW,fdtwo");
     if (fds[0]) {
-        qdev_prop_set_drive(dev, "drive", fds[0]);
+        qdev_prop_set_drive(dev, "drive", fds[0]->bdrv);
     }
     qdev_init_nofail(dev);
     sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
@@ -2030,8 +2028,8 @@  static ISADeviceInfo isa_fdc_info = {
     .qdev.vmsd  = &vmstate_isa_fdc,
     .qdev.reset = fdctrl_external_reset_isa,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].dinfo),
-        DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].dinfo),
+        DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
+        DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
@@ -2053,8 +2051,8 @@  static SysBusDeviceInfo sysbus_fdc_info = {
     .qdev.vmsd  = &vmstate_sysbus_fdc,
     .qdev.reset = fdctrl_external_reset_sysbus,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].dinfo),
-        DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].dinfo),
+        DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs),
+        DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
@@ -2066,7 +2064,7 @@  static SysBusDeviceInfo sun4m_fdc_info = {
     .qdev.vmsd  = &vmstate_sysbus_fdc,
     .qdev.reset = fdctrl_external_reset_sysbus,
     .qdev.props = (Property[]) {
-        DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].dinfo),
+        DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 0b3b7c2..a6ea70c 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2594,15 +2594,15 @@  void ide_bus_reset(IDEBus *bus)
     ide_clear_hob(bus);
 }
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+void ide_init_drive(IDEState *s, BlockDriverState *bs,
                     const char *version, const char *serial)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
 
-    s->bs = dinfo->bdrv;
-    bdrv_get_geometry(s->bs, &nb_sectors);
-    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
+    s->bs = bs;
+    bdrv_get_geometry(bs, &nb_sectors);
+    bdrv_guess_geometry(bs, &cylinders, &heads, &secs);
     s->cylinders = cylinders;
     s->heads = heads;
     s->sectors = secs;
@@ -2613,9 +2613,9 @@  void ide_init_drive(IDEState *s, DriveInfo *dinfo,
     s->smart_autosave = 1;
     s->smart_errors = 0;
     s->smart_selftest_count = 0;
-    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+    if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) {
         s->is_cdrom = 1;
-        bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
+        bdrv_set_change_cb(bs, cdrom_change_cb, s);
     }
     if (serial && *serial) {
         strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
@@ -2668,7 +2668,7 @@  void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
         dinfo = i == 0 ? hd0 : hd1;
         ide_init1(bus, i);
         if (dinfo) {
-            ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial);
+            ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, dinfo->serial);
         } else {
             ide_reset(&bus->ifs[i]);
         }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index eef1ee1..0125a9f 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -555,7 +555,7 @@  uint32_t ide_data_readw(void *opaque, uint32_t addr);
 void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+void ide_init_drive(IDEState *s, BlockDriverState *bs,
                     const char *version, const char *serial);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 0f9f22e..aff9392 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -39,7 +39,7 @@  static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
     IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base);
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
-    if (!dev->conf.dinfo) {
+    if (!dev->conf.bs) {
         fprintf(stderr, "%s: no drive specified\n", qdev->info->name);
         goto err;
     }
@@ -83,7 +83,7 @@  IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 
     dev = qdev_create(&bus->qbus, "ide-drive");
     qdev_prop_set_uint32(dev, "unit", unit);
-    qdev_prop_set_drive(dev, "drive", drive);
+    qdev_prop_set_drive(dev, "drive", drive->bdrv);
     if (qdev_init(dev) < 0)
         return NULL;
     return DO_UPCAST(IDEDevice, qdev, dev);
@@ -104,10 +104,10 @@  static int ide_drive_initfn(IDEDevice *dev)
     serial = dev->serial;
     if (!serial) {
         /* try to fall back to value set with legacy -drive serial=... */
-        serial = dev->conf.dinfo->serial;
+        serial = drive_get_serial(dev->conf.bs);
     }
 
-    ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
+    ide_init_drive(s, dev->conf.bs, dev->version, serial);
 
     if (!dev->version) {
         dev->version = qemu_strdup(s->version);
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index c39e640..a27a67b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -89,7 +89,7 @@  static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
      * specified).
      */
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
-    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo, dinfo->unit);
+    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit);
     dinfo->unit = scsidev->id;
 
     if (printinfo)
@@ -211,7 +211,7 @@  static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
             return NULL;
         }
         dev = pci_create(bus, devfn, "virtio-blk-pci");
-        qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
+        qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv);
         if (qdev_init(&dev->qdev) < 0)
             dev = NULL;
         break;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 5a8739d..45ce5c4 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -285,26 +285,41 @@  PropertyInfo qdev_prop_string = {
 
 static int parse_drive(DeviceState *dev, Property *prop, const char *str)
 {
-    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
+    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    BlockDriverState *bs;
 
-    *ptr = drive_get_by_id(str);
-    if (*ptr == NULL)
+    bs = bdrv_find(str);
+    if (bs == NULL)
         return -ENOENT;
+    if (blockdev_attach(bs, dev) < 0)
+        return -EEXIST;
+    *ptr = bs;
     return 0;
 }
 
+static void free_drive(DeviceState *dev, Property *prop)
+{
+    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+
+    if (*ptr) {
+        blockdev_detach(*ptr, dev);
+    }
+}
+
 static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
 {
-    DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
-    return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>");
+    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    return snprintf(dest, len, "%s",
+                    *ptr ? bdrv_get_device_name(*ptr) : "<null>");
 }
 
 PropertyInfo qdev_prop_drive = {
     .name  = "drive",
     .type  = PROP_TYPE_DRIVE,
-    .size  = sizeof(DriveInfo*),
+    .size  = sizeof(BlockDriverState *),
     .parse = parse_drive,
     .print = print_drive,
+    .free  = free_drive,
 };
 
 /* --- character device --- */
@@ -627,9 +642,19 @@  void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
     qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
 }
 
-void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
+void qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
 {
+    int res;
+
     qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
+    res = blockdev_attach(value, dev);
+    if (res < 0) {
+        error_report("Can't attach drive %s to %s.%s: %s",
+                     bdrv_get_device_name(value),
+                     dev->id ? dev->id : dev->info->name,
+                     name, strerror(res));
+        exit(1);
+    }
 }
 
 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
diff --git a/hw/qdev.h b/hw/qdev.h
index be5ad67..7a01a81 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -253,8 +253,8 @@  extern PropertyInfo qdev_prop_pci_devfn;
     DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*)
 #define DEFINE_PROP_VLAN(_n, _s, _f)             \
     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, VLANState*)
-#define DEFINE_PROP_DRIVE(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, DriveInfo*)
+#define DEFINE_PROP_DRIVE(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
 #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
 
@@ -275,7 +275,7 @@  void qdev_prop_set_string(DeviceState *dev, const char *name, char *value);
 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
 void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value);
 void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
-void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value);
+void qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value);
 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
 /* FIXME: Remove opaque pointer properties.  */
 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 898f442..c7c3fc9 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -262,7 +262,7 @@  static void s390_init(ram_addr_t ram_size,
         }
 
         dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390");
-        qdev_prop_set_drive(dev, "drive", dinfo);
+        qdev_prop_set_drive(dev, "drive", dinfo->bdrv);
         qdev_init_nofail(dev);
     }
 }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 055a94d..782ec18 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -84,15 +84,15 @@  void scsi_qdev_register(SCSIDeviceInfo *info)
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
 /* FIXME callers should check for failure, but don't */
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit)
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit)
 {
     const char *driver;
     DeviceState *dev;
 
-    driver = bdrv_is_sg(dinfo->bdrv) ? "scsi-generic" : "scsi-disk";
+    driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
     dev = qdev_create(&bus->qbus, driver);
     qdev_prop_set_uint32(dev, "scsi-id", unit);
-    qdev_prop_set_drive(dev, "drive", dinfo);
+    qdev_prop_set_drive(dev, "drive", bdrv);
     if (qdev_init(dev) < 0)
         return NULL;
     return DO_UPCAST(SCSIDevice, qdev, dev);
@@ -108,7 +108,7 @@  void scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
         if (dinfo == NULL) {
             continue;
         }
-        scsi_bus_legacy_add_drive(bus, dinfo, unit);
+        scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit);
     }
 }
 
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2b38984..46b526f 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1043,26 +1043,26 @@  static void scsi_destroy(SCSIDevice *dev)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
 
     scsi_disk_purge_requests(s);
-    drive_uninit(s->qdev.conf.dinfo);
 }
 
 static int scsi_disk_initfn(SCSIDevice *dev)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
+    const char *serial;
 
-    if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
+    if (!s->qdev.conf.bs) {
         error_report("scsi-disk: drive property not set");
         return -1;
     }
-    s->bs = s->qdev.conf.dinfo->bdrv;
+    s->bs = s->qdev.conf.bs;
 
     if (!s->serial) {
-        if (*dev->conf.dinfo->serial) {
-            /* try to fall back to value set with legacy -drive serial=... */
-            s->serial = qemu_strdup(dev->conf.dinfo->serial);
-        } else {
-            s->serial = qemu_strdup("0");
+        /* try to fall back to value set with legacy -drive serial=... */
+        serial = drive_get_serial(s->bs);
+        if (!*serial) {
+            serial = "0";
         }
+        s->serial = qemu_strdup(serial);
     }
 
     if (!s->version) {
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index e31060e..f283f6c 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -453,7 +453,6 @@  static void scsi_destroy(SCSIDevice *d)
         r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
         scsi_remove_request(r);
     }
-    drive_uninit(s->qdev.conf.dinfo);
 }
 
 static int scsi_generic_initfn(SCSIDevice *dev)
@@ -462,11 +461,11 @@  static int scsi_generic_initfn(SCSIDevice *dev)
     int sg_version;
     struct sg_scsi_id scsiid;
 
-    if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
+    if (!s->qdev.conf.bs) {
         error_report("scsi-generic: drive property not set");
         return -1;
     }
-    s->bs = s->qdev.conf.dinfo->bdrv;
+    s->bs = s->qdev.conf.bs;
 
     /* check we are really using a /dev/sg* file */
     if (!bdrv_is_sg(s->bs)) {
diff --git a/hw/scsi.h b/hw/scsi.h
index b668e27..8ca3c2d 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -97,7 +97,7 @@  static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
     return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
 }
 
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, DriveInfo *dinfo, int unit);
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit);
 void scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
 void scsi_dev_clear_sense(SCSIDevice *dev);
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 003bd8a..6ed06ff 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -523,20 +523,20 @@  static int usb_msd_initfn(USBDevice *dev)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
 
-    if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
+    if (!s->conf.bs) {
         error_report("usb-msd: drive property not set");
         return -1;
     }
 
     s->dev.speed = USB_SPEED_FULL;
     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.dinfo, 0);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.bs, 0);
     s->bus.qbus.allow_hotplug = 0;
     usb_msd_handle_reset(dev);
 
-    if (bdrv_key_required(s->conf.dinfo->bdrv)) {
+    if (bdrv_key_required(s->conf.bs)) {
         if (cur_mon) {
-            monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
+            monitor_read_bdrv_key_start(cur_mon, s->conf.bs,
                                         usb_msd_password_cb, s);
             s->dev.auto_attach = 0;
         } else {
@@ -595,7 +595,7 @@  static USBDevice *usb_msd_init(const char *filename)
     if (!dev) {
         return NULL;
     }
-    qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
+    qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv);
     if (qdev_init(&dev->qdev) < 0)
         return NULL;
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index cb17afa..a680512 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -500,7 +500,7 @@  VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->vdev.get_config = virtio_blk_update_config;
     s->vdev.get_features = virtio_blk_get_features;
     s->vdev.reset = virtio_blk_reset;
-    s->bs = conf->dinfo->bdrv;
+    s->bs = conf->bs;
     s->conf = conf;
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index e101fa0..63d55b8 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -547,7 +547,7 @@  static int virtio_blk_init_pci(PCIDevice *pci_dev)
         proxy->class_code != PCI_CLASS_STORAGE_OTHER)
         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
 
-    if (!proxy->block.dinfo) {
+    if (!proxy->block.bs) {
         error_report("virtio-blk-pci: drive property not set");
         return -1;
     }
@@ -567,14 +567,6 @@  static int virtio_exit_pci(PCIDevice *pci_dev)
     return msix_uninit(pci_dev);
 }
 
-static int virtio_blk_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    drive_uninit(proxy->block.dinfo);
-    return virtio_exit_pci(pci_dev);
-}
-
 static int virtio_serial_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -663,7 +655,7 @@  static PCIDeviceInfo virtio_info[] = {
         .qdev.name = "virtio-blk-pci",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_blk_init_pci,
-        .exit      = virtio_blk_exit_pci,
+        .exit      = virtio_exit_pci,
         .qdev.props = (Property[]) {
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
             DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),