aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/qdev-properties.c10
-rw-r--r--hw/scsi-disk.c2
-rw-r--r--hw/scsi-generic.c2
-rw-r--r--hw/usb-msd.c20
-rw-r--r--hw/virtio-pci.c2
5 files changed, 29 insertions, 7 deletions
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 5b7fd77d44..d7dc234e25 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -313,6 +313,15 @@ static int parse_drive(DeviceState *dev, Property *prop, const char *str)
return 0;
}
+static void free_drive(DeviceState *dev, Property *prop)
+{
+ DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
+
+ if (*ptr) {
+ blockdev_auto_del((*ptr)->bdrv);
+ }
+}
+
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
{
DriveInfo **ptr = qdev_get_prop_ptr(dev, prop);
@@ -325,6 +334,7 @@ PropertyInfo qdev_prop_drive = {
.size = sizeof(DriveInfo*),
.parse = parse_drive,
.print = print_drive,
+ .free = free_drive,
};
/* --- character device --- */
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2b3898435c..d76e640412 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1043,7 +1043,7 @@ static void scsi_destroy(SCSIDevice *dev)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
scsi_disk_purge_requests(s);
- drive_uninit(s->qdev.conf.dinfo);
+ blockdev_mark_auto_del(s->qdev.conf.dinfo->bdrv);
}
static int scsi_disk_initfn(SCSIDevice *dev)
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index e31060e944..1859c94b7c 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -453,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.conf.dinfo);
+ blockdev_mark_auto_del(s->qdev.conf.dinfo->bdrv);
}
static int scsi_generic_initfn(SCSIDevice *dev)
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 8e9718c562..3dbfcabeb1 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -522,24 +522,36 @@ static void usb_msd_password_cb(void *opaque, int err)
static int usb_msd_initfn(USBDevice *dev)
{
MSDState *s = DO_UPCAST(MSDState, dev, dev);
+ DriveInfo *dinfo = s->conf.dinfo;
- if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
+ if (!dinfo || !dinfo->bdrv) {
error_report("usb-msd: drive property not set");
return -1;
}
+ /*
+ * 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.
+ *
+ * The hack is probably a bad idea.
+ */
+ s->conf.dinfo = NULL;
+
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, dinfo, 0);
if (!s->scsi_dev) {
return -1;
}
s->bus.qbus.allow_hotplug = 0;
usb_msd_handle_reset(dev);
- if (bdrv_key_required(s->conf.dinfo->bdrv)) {
+ if (bdrv_key_required(dinfo->bdrv)) {
if (cur_mon) {
- monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
+ monitor_read_bdrv_key_start(cur_mon, dinfo->bdrv,
usb_msd_password_cb, s);
s->dev.auto_attach = 0;
} else {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index d1303b1a38..31a68fec40 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -571,7 +571,7 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
- drive_uninit(proxy->block.dinfo);
+ blockdev_mark_auto_del(proxy->block.dinfo->bdrv);
return virtio_exit_pci(pci_dev);
}