Index: qemu/block_int.h
===================================================================
--- qemu.orig/block_int.h	2010-02-10 20:27:57.836254726 +0100
+++ qemu/block_int.h	2010-02-10 23:27:55.101003645 +0100
@@ -202,4 +202,31 @@ extern BlockDriverState *bdrv_first;
 int is_windows_drive(const char *filename);
 #endif
 
+struct DriveInfo;
+
+typedef struct BlockConf {
+    struct DriveInfo *dinfo;
+    uint16_t physical_block_size;
+    uint16_t min_io_size;
+    uint32_t opt_io_size;
+} BlockConf;
+
+static inline unsigned int get_physical_block_exp(BlockConf *conf)
+{
+    unsigned int exp = 0, size;
+
+    for (size = conf->physical_block_size; size > 512; size >>= 1) {
+        exp++;
+    }
+
+    return exp;
+}
+
+#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
+    DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo),                    \
+    DEFINE_PROP_UINT16("physical_block_size", _state,                   \
+                       _conf.physical_block_size, 512),                 \
+    DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 512),  \
+    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 512)
+
 #endif /* BLOCK_INT_H */
Index: qemu/hw/s390-virtio-bus.c
===================================================================
--- qemu.orig/hw/s390-virtio-bus.c	2010-02-10 20:27:52.575275957 +0100
+++ qemu/hw/s390-virtio-bus.c	2010-02-10 23:27:55.102012375 +0100
@@ -123,7 +123,7 @@ static int s390_virtio_blk_init(VirtIOS3
 {
     VirtIODevice *vdev;
 
-    vdev = virtio_blk_init((DeviceState *)dev, dev->dinfo);
+    vdev = virtio_blk_init((DeviceState *)dev, dev->block.dinfo);
     if (!vdev) {
         return -1;
     }
@@ -337,7 +337,7 @@ static VirtIOS390DeviceInfo s390_virtio_
     .qdev.name = "virtio-blk-s390",
     .qdev.size = sizeof(VirtIOS390Device),
     .qdev.props = (Property[]) {
-        DEFINE_PROP_DRIVE("drive", VirtIOS390Device, dinfo),
+        DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, block),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
Index: qemu/hw/s390-virtio-bus.h
===================================================================
--- qemu.orig/hw/s390-virtio-bus.h	2010-02-10 20:27:52.583254306 +0100
+++ qemu/hw/s390-virtio-bus.h	2010-02-10 23:27:55.104003295 +0100
@@ -38,7 +38,7 @@ typedef struct VirtIOS390Device {
     ram_addr_t feat_offs;
     uint8_t feat_len;
     VirtIODevice *vdev;
-    DriveInfo *dinfo;
+    BlockConf block;
     NICConf nic;
     uint32_t host_features;
     /* Max. number of ports we can have for a the virtio-serial device */
Index: qemu/hw/virtio-blk.c
===================================================================
--- qemu.orig/hw/virtio-blk.c	2010-02-10 23:27:51.067254307 +0100
+++ qemu/hw/virtio-blk.c	2010-02-10 23:27:55.105016426 +0100
@@ -457,7 +457,7 @@ static int virtio_blk_load(QEMUFile *f, 
     return 0;
 }
 
-VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo)
+VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
 {
     VirtIOBlock *s;
     int cylinders, heads, secs;
@@ -470,7 +470,7 @@ VirtIODevice *virtio_blk_init(DeviceStat
     s->vdev.get_config = virtio_blk_update_config;
     s->vdev.get_features = virtio_blk_get_features;
     s->vdev.reset = virtio_blk_reset;
-    s->bs = dinfo->bdrv;
+    s->bs = conf->dinfo->bdrv;
     s->rq = NULL;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
     bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
Index: qemu/hw/virtio-pci.c
===================================================================
--- qemu.orig/hw/virtio-pci.c	2010-02-10 20:27:52.600004411 +0100
+++ qemu/hw/virtio-pci.c	2010-02-10 23:27:55.107047505 +0100
@@ -22,6 +22,7 @@
 #include "sysemu.h"
 #include "msix.h"
 #include "net.h"
+#include "block_int.h"
 #include "loader.h"
 
 /* from Linux's linux/virtio_pci.h */
@@ -92,7 +93,7 @@ typedef struct {
     uint32_t addr;
     uint32_t class_code;
     uint32_t nvectors;
-    DriveInfo *dinfo;
+    BlockConf block;
     NICConf nic;
     uint32_t host_features;
     /* Max. number of ports we can have for a the virtio-serial device */
@@ -457,11 +458,11 @@ static int virtio_blk_init_pci(PCIDevice
         proxy->class_code != PCI_CLASS_STORAGE_OTHER)
         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
 
-    if (!proxy->dinfo) {
+    if (!proxy->block.dinfo) {
         qemu_error("virtio-blk-pci: drive property not set\n");
         return -1;
     }
-    vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo);
+    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
     vdev->nvectors = proxy->nvectors;
     virtio_init_pci(proxy, vdev,
                     PCI_VENDOR_ID_REDHAT_QUMRANET,
@@ -481,7 +482,7 @@ static int virtio_blk_exit_pci(PCIDevice
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 
-    drive_uninit(proxy->dinfo);
+    drive_uninit(proxy->block.dinfo);
     return virtio_exit_pci(pci_dev);
 }
 
@@ -558,7 +559,7 @@ static PCIDeviceInfo virtio_info[] = {
         .exit      = virtio_blk_exit_pci,
         .qdev.props = (Property[]) {
             DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-            DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
+            DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
             DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_PROP_END_OF_LIST(),
Index: qemu/hw/virtio.h
===================================================================
--- qemu.orig/hw/virtio.h	2010-02-10 20:27:52.611025713 +0100
+++ qemu/hw/virtio.h	2010-02-10 23:27:55.109004413 +0100
@@ -18,6 +18,7 @@
 #include "net.h"
 #include "qdev.h"
 #include "sysemu.h"
+#include "block_int.h"
 
 /* from Linux's linux/virtio_config.h */
 
@@ -169,7 +170,7 @@ void virtio_bind_device(VirtIODevice *vd
                         void *opaque);
 
 /* Base devices.  */
-VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
+VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
Index: qemu/hw/ide/internal.h
===================================================================
--- qemu.orig/hw/ide/internal.h	2010-02-10 20:27:52.620004341 +0100
+++ qemu/hw/ide/internal.h	2010-02-10 23:27:55.113003924 +0100
@@ -7,6 +7,7 @@
  * non-internal declarations are in hw/ide.h
  */
 #include <hw/ide.h>
+#include "block_int.h"
 
 /* debug IDE devices */
 //#define DEBUG_IDE
@@ -397,6 +398,7 @@ struct IDEState {
     /* set for lba48 access */
     uint8_t lba48;
     BlockDriverState *bs;
+    BlockConf *conf;
     char version[9];
     /* ATAPI specific */
     uint8_t sense_key;
@@ -449,7 +451,7 @@ struct IDEBus {
 struct IDEDevice {
     DeviceState qdev;
     uint32_t unit;
-    DriveInfo *dinfo;
+    BlockConf conf;
     char *version;
 };
 
@@ -551,7 +553,8 @@ uint32_t ide_data_readw(void *opaque, ui
 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, const char *version);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
+    const char *version);
 void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
                qemu_irq irq);
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
Index: qemu/hw/ide/qdev.c
===================================================================
--- qemu.orig/hw/ide/qdev.c	2010-02-10 20:27:52.630254516 +0100
+++ qemu/hw/ide/qdev.c	2010-02-10 23:27:55.114007626 +0100
@@ -40,7 +40,7 @@ static int ide_qdev_init(DeviceState *qd
     IDEDeviceInfo *info = DO_UPCAST(IDEDeviceInfo, qdev, base);
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
-    if (!dev->dinfo) {
+    if (!dev->conf.dinfo) {
         fprintf(stderr, "%s: no drive specified\n", qdev->info->name);
         goto err;
     }
@@ -99,7 +99,8 @@ typedef struct IDEDrive {
 static int ide_drive_initfn(IDEDevice *dev)
 {
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
-    ide_init_drive(bus->ifs + dev->unit, dev->dinfo, dev->version);
+    ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf,
+                   dev->version);
     return 0;
 }
 
@@ -109,7 +110,7 @@ static IDEDeviceInfo ide_drive_info = {
     .init       = ide_drive_initfn,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
-        DEFINE_PROP_DRIVE("drive", IDEDrive, dev.dinfo),
+        DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
         DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),
         DEFINE_PROP_END_OF_LIST(),
     }
Index: qemu/hw/scsi-disk.c
===================================================================
--- qemu.orig/hw/scsi-disk.c	2010-02-10 20:27:57.843023968 +0100
+++ qemu/hw/scsi-disk.c	2010-02-10 23:27:55.123255565 +0100
@@ -60,6 +60,7 @@ typedef struct SCSIDiskReq {
 struct SCSIDiskState
 {
     SCSIDevice qdev;
+    BlockDriverState *bs;
     /* The qemu block layer uses a fixed 512 byte sector size.
        This is the number of 512 byte blocks in a single scsi sector.  */
     int cluster_size;
@@ -168,7 +169,7 @@ static void scsi_read_data(SCSIDevice *d
 
     r->iov.iov_len = n * 512;
     qemu_iovec_init_external(&r->qiov, &r->iov, 1);
-    r->req.aiocb = bdrv_aio_readv(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
+    r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
                               scsi_read_complete, r);
     if (r->req.aiocb == NULL)
         scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR);
@@ -179,8 +180,7 @@ static void scsi_read_data(SCSIDevice *d
 static int scsi_handle_write_error(SCSIDiskReq *r, int error)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-    BlockInterfaceErrorAction action =
-        drive_get_on_error(s->qdev.dinfo->bdrv, 0);
+    BlockInterfaceErrorAction action = drive_get_on_error(s->bs, 0);
 
     if (action == BLOCK_ERR_IGNORE) {
         bdrv_mon_event(s->qdev.dinfo->bdrv, BDRV_ACTION_IGNORE, 0);
@@ -238,7 +238,7 @@ static void scsi_write_request(SCSIDiskR
     n = r->iov.iov_len / 512;
     if (n) {
         qemu_iovec_init_external(&r->qiov, &r->iov, 1);
-        r->req.aiocb = bdrv_aio_writev(s->qdev.dinfo->bdrv, r->sector, &r->qiov, n,
+        r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
                                    scsi_write_complete, r);
         if (r->req.aiocb == NULL)
             scsi_command_complete(r, CHECK_CONDITION,
@@ -319,7 +319,6 @@ static uint8_t *scsi_get_buf(SCSIDevice 
 
 static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
 {
-    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
     int buflen = 0;
 
@@ -338,7 +337,7 @@ static int scsi_disk_emulate_inquiry(SCS
             return -1;
         }
 
-        if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
+        if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
             outbuf[buflen++] = 5;
         } else {
             outbuf[buflen++] = 0;
@@ -358,8 +357,8 @@ static int scsi_disk_emulate_inquiry(SCS
 
         case 0x80: /* Device serial number, optional */
         {
-            const char *serial = req->dev->dinfo->serial ?
-                req->dev->dinfo->serial : "0";
+            const char *serial = req->dev->conf.dinfo->serial ?
+                req->dev->conf.dinfo->serial : "0";
             int l = strlen(serial);
 
             if (l > req->cmd.xfer)
@@ -378,7 +377,7 @@ static int scsi_disk_emulate_inquiry(SCS
         case 0x83: /* Device identification page, mandatory */
         {
             int max_len = 255 - 8;
-            int id_len = strlen(bdrv_get_device_name(bdrv));
+            int id_len = strlen(bdrv_get_device_name(s->bs));
 
             if (id_len > max_len)
                 id_len = max_len;
@@ -391,7 +390,7 @@ static int scsi_disk_emulate_inquiry(SCS
             outbuf[buflen++] = 0;   // reserved
             outbuf[buflen++] = id_len; // length of data following
 
-            memcpy(outbuf+buflen, bdrv_get_device_name(bdrv), id_len);
+            memcpy(outbuf+buflen, bdrv_get_device_name(s->bs), id_len);
             buflen += id_len;
             break;
         }
@@ -429,7 +428,7 @@ static int scsi_disk_emulate_inquiry(SCS
         return buflen;
     }
 
-    if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM) {
+    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
         outbuf[0] = 5;
         outbuf[1] = 0x80;
         memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
@@ -460,7 +459,7 @@ static int scsi_disk_emulate_inquiry(SCS
 static int mode_sense_page(SCSIRequest *req, int page, uint8_t *p)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
-    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
+    BlockDriverState *bdrv = s->bs;
     int cylinders, heads, secs;
 
     switch (page) {
@@ -532,7 +531,7 @@ static int mode_sense_page(SCSIRequest *
     case 8: /* Caching page.  */
         p[0] = 8;
         p[1] = 0x12;
-        if (bdrv_enable_write_cache(s->qdev.dinfo->bdrv)) {
+        if (bdrv_enable_write_cache(s->bs)) {
             p[2] = 4; /* WCE */
         }
         return 20;
@@ -549,7 +548,7 @@ static int mode_sense_page(SCSIRequest *
         p[5] = 0xff; /* CD DA, DA accurate, RW supported,
                         RW corrected, C2 errors, ISRC,
                         UPC, Bar code */
-        p[6] = 0x2d | (bdrv_is_locked(s->qdev.dinfo->bdrv)? 2 : 0);
+        p[6] = 0x2d | (bdrv_is_locked(s->bs)? 2 : 0);
         /* Locking supported, jumper present, eject, tray */
         p[7] = 0; /* no volume & mute control, no
                      changer */
@@ -575,7 +574,6 @@ static int mode_sense_page(SCSIRequest *
 static int scsi_disk_emulate_mode_sense(SCSIRequest *req, uint8_t *outbuf)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
-    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
     uint64_t nb_sectors;
     int page, dbd, buflen;
     uint8_t *p;
@@ -588,13 +586,13 @@ static int scsi_disk_emulate_mode_sense(
 
     p[1] = 0; /* Default media type.  */
     p[3] = 0; /* Block descriptor length.  */
-    if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM ||
-        bdrv_is_read_only(bdrv)) {
+    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM ||
+        bdrv_is_read_only(s->bs)) {
         p[2] = 0x80; /* Readonly.  */
     }
     p += 4;
 
-    bdrv_get_geometry(bdrv, &nb_sectors);
+    bdrv_get_geometry(s->bs, &nb_sectors);
     if ((~dbd) & nb_sectors) {
         outbuf[3] = 8; /* Block descriptor length  */
         nb_sectors /= s->cluster_size;
@@ -635,14 +633,13 @@ static int scsi_disk_emulate_mode_sense(
 static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
-    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
     int start_track, format, msf, toclen;
     uint64_t nb_sectors;
 
     msf = req->cmd.buf[1] & 2;
     format = req->cmd.buf[2] & 0xf;
     start_track = req->cmd.buf[6];
-    bdrv_get_geometry(bdrv, &nb_sectors);
+    bdrv_get_geometry(s->bs, &nb_sectors);
     DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
     nb_sectors /= s->cluster_size;
     switch (format) {
@@ -671,13 +668,12 @@ static int scsi_disk_emulate_read_toc(SC
 static int scsi_disk_emulate_command(SCSIRequest *req, uint8_t *outbuf)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
-    BlockDriverState *bdrv = req->dev->dinfo->bdrv;
     uint64_t nb_sectors;
     int buflen = 0;
 
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        if (!bdrv_is_inserted(bdrv))
+        if (!bdrv_is_inserted(s->bs))
             goto not_ready;
 	break;
     case REQUEST_SENSE:
@@ -731,18 +727,18 @@ static int scsi_disk_emulate_command(SCS
             goto illegal_request;
         break;
     case START_STOP:
-        if (bdrv_get_type_hint(bdrv) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
+        if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM && (req->cmd.buf[4] & 2)) {
             /* load/eject medium */
-            bdrv_eject(bdrv, !(req->cmd.buf[4] & 1));
+            bdrv_eject(s->bs, !(req->cmd.buf[4] & 1));
         }
 	break;
     case ALLOW_MEDIUM_REMOVAL:
-        bdrv_set_locked(bdrv, req->cmd.buf[4] & 1);
+        bdrv_set_locked(s->bs, req->cmd.buf[4] & 1);
 	break;
     case READ_CAPACITY:
         /* The normal LEN field for this command is zero.  */
 	memset(outbuf, 0, 8);
-	bdrv_get_geometry(bdrv, &nb_sectors);
+	bdrv_get_geometry(s->bs, &nb_sectors);
         if (!nb_sectors)
             goto not_ready;
         nb_sectors /= s->cluster_size;
@@ -764,7 +760,7 @@ static int scsi_disk_emulate_command(SCS
         buflen = 8;
 	break;
     case SYNCHRONIZE_CACHE:
-        bdrv_flush(bdrv);
+        bdrv_flush(s->bs);
         break;
     case GET_CONFIGURATION:
         memset(outbuf, 0, 8);
@@ -778,7 +774,7 @@ static int scsi_disk_emulate_command(SCS
         if ((req->cmd.buf[1] & 31) == 0x10) {
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
-            bdrv_get_geometry(bdrv, &nb_sectors);
+            bdrv_get_geometry(s->bs, &nb_sectors);
             if (!nb_sectors)
                 goto not_ready;
             nb_sectors /= s->cluster_size;
@@ -993,7 +989,7 @@ static void scsi_destroy(SCSIDevice *dev
         r = DO_UPCAST(SCSIDiskReq, req, QTAILQ_FIRST(&s->qdev.requests));
         scsi_remove_request(r);
     }
-    drive_uninit(s->qdev.dinfo);
+    drive_uninit(s->qdev.conf.dinfo);
 }
 
 static int scsi_disk_initfn(SCSIDevice *dev)
@@ -1001,19 +997,20 @@ static int scsi_disk_initfn(SCSIDevice *
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
     uint64_t nb_sectors;
 
-    if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
+    if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
         qemu_error("scsi-disk: drive property not set\n");
         return -1;
     }
+    s->bs = s->qdev.conf.dinfo->bdrv;
 
-    if (bdrv_get_type_hint(s->qdev.dinfo->bdrv) == BDRV_TYPE_CDROM) {
+    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
         s->cluster_size = 4;
     } else {
         s->cluster_size = 1;
     }
     s->qdev.blocksize = 512 * s->cluster_size;
     s->qdev.type = TYPE_DISK;
-    bdrv_get_geometry(s->qdev.dinfo->bdrv, &nb_sectors);
+    bdrv_get_geometry(s->bs, &nb_sectors);
     nb_sectors /= s->cluster_size;
     if (nb_sectors)
         nb_sectors--;
@@ -1034,7 +1031,7 @@ static SCSIDeviceInfo scsi_disk_info = {
     .cancel_io    = scsi_cancel_io,
     .get_buf      = scsi_get_buf,
     .qdev.props   = (Property[]) {
-        DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.dinfo),
+        DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
         DEFINE_PROP_STRING("ver",  SCSIDiskState, version),
         DEFINE_PROP_END_OF_LIST(),
     },
Index: qemu/hw/scsi.h
===================================================================
--- qemu.orig/hw/scsi.h	2010-02-10 20:27:52.656004411 +0100
+++ qemu/hw/scsi.h	2010-02-10 23:27:55.128005460 +0100
@@ -3,6 +3,7 @@
 
 #include "qdev.h"
 #include "block.h"
+#include "block_int.h"
 
 #define SCSI_CMD_BUF_SIZE     16
 
@@ -49,7 +50,7 @@ struct SCSIDevice
 {
     DeviceState qdev;
     uint32_t id;
-    DriveInfo *dinfo;
+    BlockConf conf;
     SCSIDeviceInfo *info;
     QTAILQ_HEAD(, SCSIRequest) requests;
     int blocksize;
Index: qemu/hw/scsi-generic.c
===================================================================
--- qemu.orig/hw/scsi-generic.c	2010-02-10 20:27:52.664004551 +0100
+++ qemu/hw/scsi-generic.c	2010-02-10 23:27:55.133006368 +0100
@@ -58,6 +58,7 @@ typedef struct SCSIGenericReq {
 struct SCSIGenericState
 {
     SCSIDevice qdev;
+    BlockDriverState *bs;
     int lun;
     int driver_status;
     uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
@@ -212,7 +213,7 @@ static void scsi_read_data(SCSIDevice *d
         return;
     }
 
-    ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
+    ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
     if (ret == -1) {
         scsi_command_complete(r, -EINVAL);
         return;
@@ -263,7 +264,7 @@ static int scsi_write_data(SCSIDevice *d
         return 0;
     }
 
-    ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
+    ret = execute_command(s->bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
     if (ret == -1) {
         scsi_command_complete(r, -EINVAL);
         return 1;
@@ -357,7 +358,7 @@ static int32_t scsi_send_command(SCSIDev
             qemu_free(r->buf);
         r->buflen = 0;
         r->buf = NULL;
-        ret = execute_command(s->qdev.dinfo->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
+        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
         if (ret == -1) {
             scsi_command_complete(r, -EINVAL);
             return 0;
@@ -452,7 +453,7 @@ static void scsi_destroy(SCSIDevice *d)
         r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests));
         scsi_remove_request(r);
     }
-    drive_uninit(s->qdev.dinfo);
+    drive_uninit(s->qdev.conf.dinfo);
 }
 
 static int scsi_generic_initfn(SCSIDevice *dev)
@@ -461,26 +462,27 @@ static int scsi_generic_initfn(SCSIDevic
     int sg_version;
     struct sg_scsi_id scsiid;
 
-    if (!s->qdev.dinfo || !s->qdev.dinfo->bdrv) {
+    if (!s->qdev.conf.dinfo || !s->qdev.conf.dinfo->bdrv) {
         qemu_error("scsi-generic: drive property not set\n");
         return -1;
     }
+    s->bs = s->qdev.conf.dinfo->bdrv;
 
     /* check we are really using a /dev/sg* file */
-    if (!bdrv_is_sg(s->qdev.dinfo->bdrv)) {
+    if (!bdrv_is_sg(s->bs)) {
         qemu_error("scsi-generic: not /dev/sg*\n");
         return -1;
     }
 
     /* check we are using a driver managing SG_IO (version 3 and after */
-    if (bdrv_ioctl(s->qdev.dinfo->bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
+    if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 ||
         sg_version < 30000) {
         qemu_error("scsi-generic: scsi generic interface too old\n");
         return -1;
     }
 
     /* get LUN of the /dev/sg? */
-    if (bdrv_ioctl(s->qdev.dinfo->bdrv, SG_GET_SCSI_ID, &scsiid)) {
+    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
         qemu_error("scsi-generic: SG_GET_SCSI_ID ioctl failed\n");
         return -1;
     }
@@ -491,11 +493,11 @@ static int scsi_generic_initfn(SCSIDevic
     s->qdev.type = scsiid.scsi_type;
     DPRINTF("device type %d\n", s->qdev.type);
     if (s->qdev.type == TYPE_TAPE) {
-        s->qdev.blocksize = get_stream_blocksize(s->qdev.dinfo->bdrv);
+        s->qdev.blocksize = get_stream_blocksize(s->bs);
         if (s->qdev.blocksize == -1)
             s->qdev.blocksize = 0;
     } else {
-        s->qdev.blocksize = get_blocksize(s->qdev.dinfo->bdrv);
+        s->qdev.blocksize = get_blocksize(s->bs);
         /* removable media returns 0 if not present */
         if (s->qdev.blocksize <= 0) {
             if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
@@ -522,7 +524,7 @@ static SCSIDeviceInfo scsi_generic_info 
     .cancel_io    = scsi_cancel_io,
     .get_buf      = scsi_get_buf,
     .qdev.props   = (Property[]) {
-        DEFINE_PROP_DRIVE("drive", SCSIGenericState, qdev.dinfo),
+        DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
Index: qemu/hw/usb-msd.c
===================================================================
--- qemu.orig/hw/usb-msd.c	2010-02-10 20:27:52.676004132 +0100
+++ qemu/hw/usb-msd.c	2010-02-10 23:27:55.139006508 +0100
@@ -47,7 +47,7 @@ typedef struct {
     uint32_t residue;
     uint32_t tag;
     SCSIBus bus;
-    DriveInfo *dinfo;
+    BlockConf conf;
     SCSIDevice *scsi_dev;
     int result;
     /* For async completion.  */
@@ -523,20 +523,20 @@ static int usb_msd_initfn(USBDevice *dev
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
 
-    if (!s->dinfo || !s->dinfo->bdrv) {
+    if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
         qemu_error("usb-msd: drive property not set\n");
         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->dinfo, 0);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.dinfo, 0);
     s->bus.qbus.allow_hotplug = 0;
     usb_msd_handle_reset(dev);
 
-    if (bdrv_key_required(s->dinfo->bdrv)) {
+    if (bdrv_key_required(s->conf.dinfo->bdrv)) {
         if (s->dev.qdev.hotplugged) {
-            monitor_read_bdrv_key_start(cur_mon, s->dinfo->bdrv,
+            monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
                                         usb_msd_password_cb, s);
             s->dev.auto_attach = 0;
         } else {
@@ -611,7 +611,7 @@ static struct USBDeviceInfo msd_info = {
     .usbdevice_name = "disk",
     .usbdevice_init = usb_msd_init,
     .qdev.props     = (Property[]) {
-        DEFINE_PROP_DRIVE("drive", MSDState, dinfo),
+        DEFINE_BLOCK_PROPERTIES(MSDState, conf),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
Index: qemu/hw/ide/core.c
===================================================================
--- qemu.orig/hw/ide/core.c	2010-02-10 20:27:57.843023968 +0100
+++ qemu/hw/ide/core.c	2010-02-10 23:27:55.165337978 +0100
@@ -2594,7 +2594,8 @@ void ide_bus_reset(IDEBus *bus)
     ide_clear_hob(bus);
 }
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
+        const char *version)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
@@ -2619,6 +2620,9 @@ void ide_init_drive(IDEState *s, DriveIn
         }
         strncpy(s->drive_serial_str, drive_get_serial(s->bs),
                 sizeof(s->drive_serial_str));
+        if (conf) {
+            s->conf = conf;
+        }
     }
     if (strlen(s->drive_serial_str) == 0)
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
@@ -2648,9 +2652,9 @@ void ide_init2(IDEBus *bus, DriveInfo *h
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
         if (i == 0)
-            ide_init_drive(s, hd0, NULL);
+            ide_init_drive(s, hd0, NULL, NULL);
         if (i == 1)
-            ide_init_drive(s, hd1, NULL);
+            ide_init_drive(s, hd1, NULL, NULL);
     }
     bus->irq = irq;
 }
