From: Kevin Wolf <kwolf@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: hch@lst.de, qemu-devel@nongnu.org, kraxel@redhat.com
Subject: [Qemu-devel] Re: [PATCH 08/12] block: Catch attempt to attach multiple devices to a blockdev
Date: Tue, 29 Jun 2010 15:32:56 +0200 [thread overview]
Message-ID: <4C29F608.5000104@redhat.com> (raw)
In-Reply-To: <1277484812-22012-9-git-send-email-armbru@redhat.com>
Am 25.06.2010 18:53, schrieb Markus Armbruster:
> 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>
> ---
> block.c | 22 ++++++++++++++++++++++
> block.h | 3 +++
> block_int.h | 2 ++
> hw/fdc.c | 10 +++++-----
> hw/ide/qdev.c | 2 +-
> hw/pci-hotplug.c | 5 ++++-
> hw/qdev-properties.c | 21 ++++++++++++++++++++-
> hw/qdev.h | 3 ++-
> hw/s390-virtio.c | 2 +-
> hw/scsi-bus.c | 4 +++-
> hw/usb-msd.c | 11 +++++++----
> 11 files changed, 70 insertions(+), 15 deletions(-)
>
> diff --git a/block.c b/block.c
> index e71a771..5e0ffa0 100644
> --- a/block.c
> +++ b/block.c
> @@ -659,6 +659,8 @@ void bdrv_close_all(void)
>
> void bdrv_delete(BlockDriverState *bs)
> {
> + assert(!bs->peer);
> +
> /* remove from list, if necessary */
> if (bs->device_name[0] != '\0') {
> QTAILQ_REMOVE(&bdrv_states, bs, list);
> @@ -672,6 +674,26 @@ void bdrv_delete(BlockDriverState *bs)
> qemu_free(bs);
> }
>
> +int bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
> +{
> + if (bs->peer) {
> + return -EBUSY;
> + }
> + bs->peer = qdev;
> + return 0;
> +}
> +
> +void bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
> +{
> + assert(bs->peer == qdev);
> + bs->peer = NULL;
> +}
> +
> +DeviceState *bdrv_get_attached(BlockDriverState *bs)
> +{
> + return bs->peer;
> +}
> +
> /*
> * Run consistency checks on an image
> *
> diff --git a/block.h b/block.h
> index 6a157f4..88ac06e 100644
> --- a/block.h
> +++ b/block.h
> @@ -71,6 +71,9 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
> int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
> BlockDriver *drv);
> void bdrv_close(BlockDriverState *bs);
> +int bdrv_attach(BlockDriverState *bs, DeviceState *qdev);
> +void bdrv_detach(BlockDriverState *bs, DeviceState *qdev);
> +DeviceState *bdrv_get_attached(BlockDriverState *bs);
> int bdrv_check(BlockDriverState *bs);
> int bdrv_read(BlockDriverState *bs, int64_t sector_num,
> uint8_t *buf, int nb_sectors);
> diff --git a/block_int.h b/block_int.h
> index e60aed4..a94b801 100644
> --- a/block_int.h
> +++ b/block_int.h
> @@ -148,6 +148,8 @@ struct BlockDriverState {
> BlockDriver *drv; /* NULL means no media */
> void *opaque;
>
> + DeviceState *peer;
> +
> char filename[1024];
> char backing_file[1024]; /* if non zero, the image is a diff of
> this file image */
> diff --git a/hw/fdc.c b/hw/fdc.c
> index 08712bc..1496cfa 100644
> --- a/hw/fdc.c
> +++ b/hw/fdc.c
> @@ -1860,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]->bdrv);
> + qdev_prop_set_drive_nofail(&dev->qdev, "driveA", fds[0]->bdrv);
> }
> if (fds[1]) {
> - qdev_prop_set_drive(&dev->qdev, "driveB", fds[1]->bdrv);
> + qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv);
> }
> if (qdev_init(&dev->qdev) < 0)
> return NULL;
> @@ -1882,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]->bdrv);
> + qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
> }
> if (fds[1]) {
> - qdev_prop_set_drive(dev, "driveB", fds[1]->bdrv);
> + qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
> }
> qdev_init_nofail(dev);
> sysbus_connect_irq(&sys->busdev, 0, irq);
> @@ -1903,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]->bdrv);
> + qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv);
> }
> qdev_init_nofail(dev);
> sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
> diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
> index 3bb94c6..b4bc5ac 100644
> --- a/hw/ide/qdev.c
> +++ b/hw/ide/qdev.c
> @@ -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->bdrv);
> + qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
> qdev_init_nofail(dev);
> return DO_UPCAST(IDEDevice, qdev, dev);
> }
> diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
> index d743192..b47e01e 100644
> --- a/hw/pci-hotplug.c
> +++ b/hw/pci-hotplug.c
> @@ -214,7 +214,10 @@ 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->bdrv);
> + if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
> + dev = NULL;
> + break;
> + }
I think in error cases we'll leak dev.
> if (qdev_init(&dev->qdev) < 0)
> dev = NULL;
> break;
> diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
> index 257233e..caf6798 100644
> --- a/hw/qdev-properties.c
> +++ b/hw/qdev-properties.c
> @@ -291,6 +291,8 @@ static int parse_drive(DeviceState *dev, Property *prop, const char *str)
> bs = bdrv_find(str);
> if (bs == NULL)
> return -ENOENT;
> + if (bdrv_attach(bs, dev) < 0)
> + return -EEXIST;
> *ptr = bs;
> return 0;
> }
> @@ -300,6 +302,7 @@ static void free_drive(DeviceState *dev, Property *prop)
> BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
>
> if (*ptr) {
> + bdrv_detach(*ptr, dev);
> blockdev_auto_del(*ptr);
> }
> }
> @@ -640,11 +643,27 @@ 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, BlockDriverState *value)
> +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
> {
> + int res;
> +
> qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
> + res = bdrv_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));
> + }
> + return res;
> }
>
> +void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
> +{
> + if (qdev_prop_set_drive(dev, name, value) < 0) {
> + exit(1);
> + }
> +}
> void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
> {
> qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
> diff --git a/hw/qdev.h b/hw/qdev.h
> index 7a01a81..cbc89f2 100644
> --- a/hw/qdev.h
> +++ b/hw/qdev.h
> @@ -275,7 +275,8 @@ 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, BlockDriverState *value);
> +int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
> +void qdev_prop_set_drive_nofail(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 c7c3fc9..6af58e2 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->bdrv);
> + qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
> qdev_init_nofail(dev);
> }
> }
> diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
> index 2c58aca..9678328 100644
> --- a/hw/scsi-bus.c
> +++ b/hw/scsi-bus.c
> @@ -91,7 +91,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int
> 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", bdrv);
> + if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
> + return NULL;
> + }
As we do here.
> if (qdev_init(dev) < 0)
> return NULL;
> return DO_UPCAST(SCSIDevice, qdev, dev);
> diff --git a/hw/usb-msd.c b/hw/usb-msd.c
> index 19a14b4..008cc0f 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,9 @@ 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) {
> + return NULL;
> + }
> if (qdev_init(&dev->qdev) < 0)
> return NULL;
And here.
Kevin
next prev parent reply other threads:[~2010-06-29 13:33 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-25 16:53 [Qemu-devel] [PATCH 00/12] More block-related fixes and cleanups Markus Armbruster
2010-06-25 16:53 ` [Qemu-devel] [PATCH 01/12] scsi: scsi_bus_legacy_handle_cmdline() can fail, fix callers Markus Armbruster
2010-06-25 19:39 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 02/12] ide: Make it explicit that ide_create_drive() can't fail Markus Armbruster
2010-06-25 19:40 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 03/12] blockdev: Remove drive_get_serial() Markus Armbruster
2010-06-25 19:41 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 04/12] blockdev: New drive_of_blockdev() Markus Armbruster
2010-06-25 19:42 ` [Qemu-devel] " Christoph Hellwig
2010-06-26 5:32 ` Markus Armbruster
2010-06-26 9:46 ` Christoph Hellwig
2010-06-26 14:46 ` Markus Armbruster
2010-06-27 9:36 ` Christoph Hellwig
2010-06-28 9:58 ` Paolo Bonzini
2010-06-29 8:57 ` Markus Armbruster
2010-06-25 16:53 ` [Qemu-devel] [PATCH 05/12] blockdev: Clean up automatic drive deletion Markus Armbruster
2010-06-26 9:48 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 06/12] qdev: Decouple qdev_prop_drive from DriveInfo Markus Armbruster
2010-06-26 10:09 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 07/12] blockdev: drive_get_by_id() is no longer used, remove Markus Armbruster
2010-06-26 10:09 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 08/12] block: Catch attempt to attach multiple devices to a blockdev Markus Armbruster
2010-06-26 10:11 ` [Qemu-devel] " Christoph Hellwig
2010-06-26 14:44 ` Markus Armbruster
2010-06-27 9:36 ` Christoph Hellwig
2010-06-28 8:24 ` Kevin Wolf
2010-06-28 10:16 ` Christoph Hellwig
2010-06-28 10:26 ` Kevin Wolf
2010-06-30 11:52 ` Markus Armbruster
2010-06-30 12:13 ` Kevin Wolf
2010-06-29 8:06 ` Gerd Hoffmann
2010-06-30 11:33 ` Markus Armbruster
2010-06-29 13:32 ` Kevin Wolf [this message]
2010-06-29 14:29 ` Markus Armbruster
2010-06-29 14:58 ` [Qemu-devel] [PATCH v2 " Markus Armbruster
2010-06-25 16:53 ` [Qemu-devel] [PATCH 09/12] savevm: Survive hot-unplug of snapshot device Markus Armbruster
2010-06-26 10:12 ` [Qemu-devel] " Christoph Hellwig
2010-06-30 11:28 ` Markus Armbruster
2010-06-30 13:37 ` Kevin Wolf
2010-06-30 16:34 ` Markus Armbruster
2010-06-25 16:53 ` [Qemu-devel] [PATCH 10/12] block: Fix virtual media change for if=none Markus Armbruster
2010-06-26 10:14 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 11/12] ide: Make PIIX and ISA IDE init functions return the qdev Markus Armbruster
2010-06-26 10:14 ` [Qemu-devel] " Christoph Hellwig
2010-06-25 16:53 ` [Qemu-devel] [PATCH 12/12] pc: Fix CMOS info for drives defined with -device Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C29F608.5000104@redhat.com \
--to=kwolf@redhat.com \
--cc=armbru@redhat.com \
--cc=hch@lst.de \
--cc=kraxel@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).