diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index c3bdedc..8327e55 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -138,7 +138,7 @@ common-obj-$(CONFIG_MAX111X) += max111x.o
 common-obj-$(CONFIG_DS1338) += ds1338.o
 common-obj-y += i2c.o smbus.o smbus_eeprom.o
 common-obj-y += eeprom93xx.o
-common-obj-y += scsi-disk.o cdrom.o hd-geometry.o
+common-obj-y += scsi-disk.o cdrom.o hd-geometry.o block-common.o
 common-obj-y += scsi-generic.o scsi-bus.o
 common-obj-y += hid.o
 common-obj-$(CONFIG_SSI) += ssi.o
diff --git a/hw/block-common.c b/hw/block-common.c
new file mode 100644
index 0000000..036334b
--- /dev/null
+++ b/hw/block-common.c
@@ -0,0 +1,24 @@
+/*
+ * Common code for block device models
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "blockdev.h"
+#include "hw/block-common.h"
+
+void blkconf_serial(BlockConf *conf, char **serial)
+{
+    DriveInfo *dinfo;
+
+    if (!*serial) {
+        /* try to fall back to value set with legacy -drive serial=... */
+        dinfo = drive_get_by_blockdev(conf->bs);
+        if (*dinfo->serial) {
+            *serial = g_strdup(dinfo->serial);
+        }
+    }
+}
diff --git a/hw/block-common.h b/hw/block-common.h
index f0d509b..52bddda 100644
--- a/hw/block-common.h
+++ b/hw/block-common.h
@@ -57,6 +57,9 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
     DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
     DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0)
 
+/* Configuration helpers */
+
+void blkconf_serial(BlockConf *conf, char **serial);
 
 /* Hard disk geometry */
 
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index de9db3b..7fe803c 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -142,7 +142,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
 {
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
     IDEState *s = bus->ifs + dev->unit;
-    const char *serial;
     DriveInfo *dinfo;
 
     if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) {
@@ -150,14 +149,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
         return -1;
     }
 
-    serial = dev->serial;
-    if (!serial) {
-        /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(dev->conf.bs);
-        if (*dinfo->serial) {
-            serial = dinfo->serial;
-        }
-    }
+    blkconf_serial(&dev->conf, &dev->serial);
 
     if (!dev->conf.cyls && !dev->conf.heads && !dev->conf.secs) {
         /* try to fall back to value set with legacy -drive cyls=... */
@@ -177,7 +169,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     }
 
     if (ide_init_drive(s, dev->conf.bs, kind,
-                       dev->version, serial, dev->model, dev->wwn,
+                       dev->version, dev->serial, dev->model, dev->wwn,
                        dev->conf.cyls, dev->conf.heads, dev->conf.secs,
                        dev->chs_trans) < 0) {
         return -1;
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 0a182f9..39a07d7 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1777,13 +1777,7 @@ static int scsi_initfn(SCSIDevice *dev)
         }
     }
 
-    if (!s->serial) {
-        /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(s->qdev.conf.bs);
-        if (*dinfo->serial) {
-            s->serial = g_strdup(dinfo->serial);
-        }
-    }
+    blkconf_serial(&s->qdev.conf, &s->serial);
 
     if (!s->version) {
         s->version = g_strdup(qemu_get_version());
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 251e7de..7fa8b83 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -532,13 +532,14 @@ static int usb_msd_initfn(USBDevice *dev)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
     BlockDriverState *bs = s->conf.bs;
-    DriveInfo *dinfo;
 
     if (!bs) {
         error_report("drive property not set");
         return -1;
     }
 
+    blkconf_serial(&s->conf, &s->serial);
+
     /*
      * Hack alert: this pretends to be a block device, but it's really
      * a SCSI bus that can serve only a single device, which it
@@ -551,13 +552,6 @@ static int usb_msd_initfn(USBDevice *dev)
     bdrv_detach_dev(bs, &s->dev.qdev);
     s->conf.bs = NULL;
 
-    if (!s->serial) {
-        /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(bs);
-        if (*dinfo->serial) {
-            s->serial = strdup(dinfo->serial);
-        }
-    }
     if (s->serial) {
         usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial);
     } else {
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 3885904..ba087bc 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -600,13 +600,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
         return NULL;
     }
 
-    if (!blk->serial) {
-        /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(blk->conf.bs);
-        if (*dinfo->serial) {
-            blk->serial = strdup(dinfo->serial);
-        }
-    }
+    blkconf_serial(&blk->conf, &blk->serial);
 
     s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                           sizeof(struct virtio_blk_config),
