aboutsummaryrefslogtreecommitdiff
path: root/hw/usb-msd.c
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2010-06-29 16:58:30 +0200
committerKevin Wolf <kwolf@redhat.com>2010-07-02 13:18:02 +0200
commit18846dee1a795b4345ac0bd10b70a3a46fd14287 (patch)
treeae5d0224a6e9733c38835c39fab70e5f42393867 /hw/usb-msd.c
parentdfb0acd88782573e075251ef323e23a4bffdbf93 (diff)
block: Catch attempt to attach multiple devices to a blockdev
For instance, -device scsi-disk,drive=foo -device scsi-disk,drive=foo happily creates two SCSI disks connected to the same block device. It's all downhill from there. Device usb-storage deliberately attaches twice to the same blockdev, which fails with the fix in place. Detach before the second attach there. Also catch attempt to delete while a guest device model is attached. Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/usb-msd.c')
-rw-r--r--hw/usb-msd.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 19a14b4f80..65e9624e54 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -532,12 +532,13 @@ static int usb_msd_initfn(USBDevice *dev)
/*
* 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
- * creates automatically. Two drive properties pointing to the
- * same drive is not good: free_drive() dies for the second one.
- * Zap the one we're not going to use.
+ * creates automatically. But first it needs to detach from its
+ * blockdev, or else scsi_bus_legacy_add_drive() dies when it
+ * attaches again.
*
* The hack is probably a bad idea.
*/
+ bdrv_detach(bs, &s->dev.qdev);
s->conf.bs = NULL;
s->dev.speed = USB_SPEED_FULL;
@@ -609,7 +610,10 @@ static USBDevice *usb_msd_init(const char *filename)
if (!dev) {
return NULL;
}
- qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv);
+ if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+ qdev_free(&dev->qdev);
+ return NULL;
+ }
if (qdev_init(&dev->qdev) < 0)
return NULL;