diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-08-28 17:08:13 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-08-28 17:08:13 +0100 |
commit | a6aebb38ba4682951ab04fe6d6e6b169bd9e4dca (patch) | |
tree | 7431ca40c5bc6882e9122326c7a2d6b140c5ba56 /hw/scsi | |
parent | 38a01e55d268aeba68c84eea425252e7f810feaf (diff) | |
parent | d1dd32af6f37e5bb8e6b2024d07fce74f510a668 (diff) | |
download | qemu-a6aebb38ba4682951ab04fe6d6e6b169bd9e4dca.zip qemu-a6aebb38ba4682951ab04fe6d6e6b169bd9e4dca.tar.gz qemu-a6aebb38ba4682951ab04fe6d6e6b169bd9e4dca.tar.bz2 |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
SCSI patches include bug fixes from Fam and Peter, improved error
reporting from Fam and a fix for DPRINTF bitrot. Memory patches try
again to initialize name from the QOM name.
# gpg: Signature made Thu 28 Aug 2014 15:10:31 BST using RSA key ID 9B4D86F2
# gpg: Good signature from "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: aka "Paolo Bonzini <bonzini@gnu.org>"
* remotes/bonzini/tags/for-upstream:
memory: Lazy init name from QOM name as needed
xen: hvm: Abstract away memory region name ref
xen-hvm: Constify string
virtio-scsi: Report error if num_queues is 0 or too large
scsi-generic: remove superfluous DPRINTF avoid to break compiling
block/iscsi: fix memory corruption on iscsi resize
scsi-bus: Convert DeviceClass init to realize
block: Pass errp in blkconf_geometry
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/scsi')
-rw-r--r-- | hw/scsi/lsi53c895a.c | 1 | ||||
-rw-r--r-- | hw/scsi/scsi-bus.c | 70 | ||||
-rw-r--r-- | hw/scsi/scsi-disk.c | 83 | ||||
-rw-r--r-- | hw/scsi/scsi-generic.c | 40 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi.c | 6 |
5 files changed, 104 insertions, 96 deletions
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 513ea47..d9b4c7e 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -19,6 +19,7 @@ #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" #include "sysemu/dma.h" +#include "qemu/error-report.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 6f4462b..954c607 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -36,20 +36,19 @@ static const TypeInfo scsi_bus_info = { }; static int next_scsi_bus; -static int scsi_device_init(SCSIDevice *s) +static void scsi_device_realize(SCSIDevice *s, Error **errp) { SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); - if (sc->init) { - return sc->init(s); + if (sc->realize) { + sc->realize(s, errp); } - return 0; } -static void scsi_device_destroy(SCSIDevice *s) +static void scsi_device_unrealize(SCSIDevice *s, Error **errp) { SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); - if (sc->destroy) { - sc->destroy(s); + if (sc->unrealize) { + sc->unrealize(s, errp); } } @@ -143,24 +142,24 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state) } } -static int scsi_qdev_init(DeviceState *qdev) +static void scsi_qdev_realize(DeviceState *qdev, Error **errp) { SCSIDevice *dev = SCSI_DEVICE(qdev); SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); SCSIDevice *d; - int rc = -1; + Error *local_err = NULL; if (dev->channel > bus->info->max_channel) { - error_report("bad scsi channel id: %d", dev->channel); - goto err; + error_setg(errp, "bad scsi channel id: %d", dev->channel); + return; } if (dev->id != -1 && dev->id > bus->info->max_target) { - error_report("bad scsi device id: %d", dev->id); - goto err; + error_setg(errp, "bad scsi device id: %d", dev->id); + return; } if (dev->lun != -1 && dev->lun > bus->info->max_lun) { - error_report("bad scsi device lun: %d", dev->lun); - goto err; + error_setg(errp, "bad scsi device lun: %d", dev->lun); + return; } if (dev->id == -1) { @@ -172,8 +171,8 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, ++id, dev->lun); } while (d && d->lun == dev->lun && id < bus->info->max_target); if (d && d->lun == dev->lun) { - error_report("no free target"); - goto err; + error_setg(errp, "no free target"); + return; } dev->id = id; } else if (dev->lun == -1) { @@ -182,43 +181,41 @@ static int scsi_qdev_init(DeviceState *qdev) d = scsi_device_find(bus, dev->channel, dev->id, ++lun); } while (d && d->lun == lun && lun < bus->info->max_lun); if (d && d->lun == lun) { - error_report("no free lun"); - goto err; + error_setg(errp, "no free lun"); + return; } dev->lun = lun; } else { d = scsi_device_find(bus, dev->channel, dev->id, dev->lun); assert(d); if (d->lun == dev->lun && dev != d) { - error_report("lun already used by '%s'", d->qdev.id); - goto err; + error_setg(errp, "lun already used by '%s'", d->qdev.id); + return; } } QTAILQ_INIT(&dev->requests); - rc = scsi_device_init(dev); - if (rc == 0) { - dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, - dev); + scsi_device_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; } + dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, + dev); if (bus->info->hotplug) { bus->info->hotplug(bus, dev); } - -err: - return rc; } -static int scsi_qdev_exit(DeviceState *qdev) +static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) { SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->vmsentry) { qemu_del_vm_change_state_handler(dev->vmsentry); } - scsi_device_destroy(dev); - return 0; + scsi_device_unrealize(dev, errp); } /* handle legacy '-drive if=scsi,...' cmd line args */ @@ -273,6 +270,7 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp) scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL, &err); if (err != NULL) { + error_report("%s", error_get_pretty(err)); error_propagate(errp, err); break; } @@ -1992,11 +1990,11 @@ static void scsi_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); set_bit(DEVICE_CATEGORY_STORAGE, k->categories); - k->bus_type = TYPE_SCSI_BUS; - k->init = scsi_qdev_init; - k->unplug = scsi_qdev_unplug; - k->exit = scsi_qdev_exit; - k->props = scsi_props; + k->bus_type = TYPE_SCSI_BUS; + k->realize = scsi_qdev_realize; + k->unplug = scsi_qdev_unplug; + k->unrealize = scsi_qdev_unrealize; + k->props = scsi_props; } static const TypeInfo scsi_device_type_info = { diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d55521d..e34a544 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2151,7 +2151,7 @@ static void scsi_disk_reset(DeviceState *dev) s->tray_open = 0; } -static void scsi_destroy(SCSIDevice *dev) +static void scsi_unrealize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); @@ -2234,25 +2234,29 @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev) } } -static int scsi_initfn(SCSIDevice *dev) +static void scsi_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); + Error *err = NULL; if (!s->qdev.conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) && !bdrv_is_inserted(s->qdev.conf.bs)) { - error_report("Device needs media, but drive is empty"); - return -1; + error_setg(errp, "Device needs media, but drive is empty"); + return; } blkconf_serial(&s->qdev.conf, &s->serial); - if (dev->type == TYPE_DISK - && blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) { - return -1; + if (dev->type == TYPE_DISK) { + blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err); + if (err) { + error_propagate(errp, err); + return; + } } if (s->qdev.conf.discard_granularity == -1) { @@ -2268,8 +2272,8 @@ static int scsi_initfn(SCSIDevice *dev) } if (bdrv_is_sg(s->qdev.conf.bs)) { - error_report("unwanted /dev/sg*"); - return -1; + error_setg(errp, "unwanted /dev/sg*"); + return; } if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && @@ -2282,10 +2286,9 @@ static int scsi_initfn(SCSIDevice *dev) bdrv_iostatus_enable(s->qdev.conf.bs); add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL); - return 0; } -static int scsi_hd_initfn(SCSIDevice *dev) +static void scsi_hd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); s->qdev.blocksize = s->qdev.conf.logical_block_size; @@ -2293,10 +2296,10 @@ static int scsi_hd_initfn(SCSIDevice *dev) if (!s->product) { s->product = g_strdup("QEMU HARDDISK"); } - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } -static int scsi_cd_initfn(SCSIDevice *dev) +static void scsi_cd_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); s->qdev.blocksize = 2048; @@ -2305,22 +2308,26 @@ static int scsi_cd_initfn(SCSIDevice *dev) if (!s->product) { s->product = g_strdup("QEMU CD-ROM"); } - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } -static int scsi_disk_initfn(SCSIDevice *dev) +static void scsi_disk_realize(SCSIDevice *dev, Error **errp) { DriveInfo *dinfo; + Error *local_err = NULL; if (!dev->conf.bs) { - return scsi_initfn(dev); /* ... and die there */ + scsi_realize(dev, &local_err); + assert(local_err); + error_propagate(errp, local_err); + return; } dinfo = drive_get_by_blockdev(dev->conf.bs); if (dinfo->media_cd) { - return scsi_cd_initfn(dev); + scsi_cd_realize(dev, errp); } else { - return scsi_hd_initfn(dev); + scsi_hd_realize(dev, errp); } } @@ -2452,35 +2459,35 @@ static int get_device_type(SCSIDiskState *s) return 0; } -static int scsi_block_initfn(SCSIDevice *dev) +static void scsi_block_realize(SCSIDevice *dev, Error **errp) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); int sg_version; int rc; if (!s->qdev.conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } /* check we are using a driver managing SG_IO (version 3 and after) */ rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_report("cannot get SG_IO version number: %s. " + error_setg(errp, "cannot get SG_IO version number: %s. " "Is this a SCSI device?", strerror(-rc)); - return -1; + return; } if (sg_version < 30000) { - error_report("scsi generic interface too old"); - return -1; + error_setg(errp, "scsi generic interface too old"); + return; } /* get device type from INQUIRY data */ rc = get_device_type(s); if (rc < 0) { - error_report("INQUIRY failed"); - return -1; + error_setg(errp, "INQUIRY failed"); + return; } /* Make a guess for the block size, we'll fix it when the guest sends. @@ -2498,7 +2505,7 @@ static int scsi_block_initfn(SCSIDevice *dev) */ s->features |= (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS); - return scsi_initfn(&s->qdev); + scsi_realize(&s->qdev, errp); } static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf) @@ -2621,8 +2628,8 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_hd_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_hd_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; @@ -2652,8 +2659,8 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_cd_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_cd_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; @@ -2682,8 +2689,8 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_block_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_block_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_block_new_request; sc->parse_cdb = scsi_block_parse_cdb; dc->fw_name = "disk"; @@ -2720,8 +2727,8 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_disk_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_disk_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 0b2ff90..20587b4 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -303,9 +303,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) SCSIDevice *s = r->req.dev; int ret; - DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag, - r->req.cmd.xfer, cmd[0]); - #ifdef DEBUG_SCSI { int i; @@ -386,49 +383,49 @@ static void scsi_generic_reset(DeviceState *dev) scsi_device_purge_requests(s, SENSE_CODE(RESET)); } -static void scsi_destroy(SCSIDevice *s) +static void scsi_unrealize(SCSIDevice *s, Error **errp) { scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE)); blockdev_mark_auto_del(s->conf.bs); } -static int scsi_generic_initfn(SCSIDevice *s) +static void scsi_generic_realize(SCSIDevice *s, Error **errp) { int rc; int sg_version; struct sg_scsi_id scsiid; if (!s->conf.bs) { - error_report("drive property not set"); - return -1; + error_setg(errp, "drive property not set"); + return; } if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { - error_report("Device doesn't support drive option werror"); - return -1; + error_setg(errp, "Device doesn't support drive option werror"); + return; } if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { - error_report("Device doesn't support drive option rerror"); - return -1; + error_setg(errp, "Device doesn't support drive option rerror"); + return; } /* check we are using a driver managing SG_IO (version 3 and after */ rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_report("cannot get SG_IO version number: %s. " - "Is this a SCSI device?", - strerror(-rc)); - return -1; + error_setg(errp, "cannot get SG_IO version number: %s. " + "Is this a SCSI device?", + strerror(-rc)); + return; } if (sg_version < 30000) { - error_report("scsi generic interface too old"); - return -1; + error_setg(errp, "scsi generic interface too old"); + return; } /* get LUN of the /dev/sg? */ if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) { - error_report("SG_GET_SCSI_ID ioctl failed"); - return -1; + error_setg(errp, "SG_GET_SCSI_ID ioctl failed"); + return; } /* define device state */ @@ -460,7 +457,6 @@ static int scsi_generic_initfn(SCSIDevice *s) } DPRINTF("block size %d\n", s->blocksize); - return 0; } const SCSIReqOps scsi_generic_req_ops = { @@ -501,8 +497,8 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); - sc->init = scsi_generic_initfn; - sc->destroy = scsi_destroy; + sc->realize = scsi_generic_realize; + sc->unrealize = scsi_unrealize; sc->alloc_req = scsi_new_request; sc->parse_cdb = scsi_generic_parse_cdb; dc->fw_name = "disk"; diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 2dd9255..86aba88 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -699,6 +699,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp, virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI, sizeof(VirtIOSCSIConfig)); + if (s->conf.num_queues <= 0 || s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX) { + error_setg(errp, "Invalid number of queues (= %" PRId32 "), " + "must be a positive integer less than %d.", + s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX); + return; + } s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *)); s->sense_size = VIRTIO_SCSI_SENSE_SIZE; s->cdb_size = VIRTIO_SCSI_CDB_SIZE; |