Commit 18846dee authored by Markus Armbruster's avatar Markus Armbruster Committed by Kevin Wolf
Browse files

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: default avatarMarkus Armbruster <armbru@redhat.com>
Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parent dfb0acd8
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -665,6 +665,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);
@@ -678,6 +680,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
 *
+3 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+5 −5
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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);
}
Loading