diff options
author | Markus Armbruster <armbru@redhat.com> | 2010-06-29 16:58:30 +0200 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2010-07-02 13:18:02 +0200 |
commit | 18846dee1a795b4345ac0bd10b70a3a46fd14287 (patch) | |
tree | ae5d0224a6e9733c38835c39fab70e5f42393867 /hw/qdev-properties.c | |
parent | dfb0acd88782573e075251ef323e23a4bffdbf93 (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/qdev-properties.c')
-rw-r--r-- | hw/qdev-properties.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 49b33773b2..7e3e99efcb 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -311,6 +311,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; } @@ -320,6 +322,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); } } @@ -660,11 +663,28 @@ 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; + + 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 -1; + } qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); + return 0; } +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); |