summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-02-15 09:22:54 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2012-02-24 14:54:51 +0100
commitd3d250bddb3f6aa6c26e9dadf10e82d9fd8bfce3 (patch)
tree574b7eda22a6880e41830d9c4bc98e1f695aa1ec
parent9fac25bf6ee6e3291ccb27feb9ad9b63506c7a60 (diff)
downloadqemu-d3d250bddb3f6aa6c26e9dadf10e82d9fd8bfce3.tar.gz
qemu-d3d250bddb3f6aa6c26e9dadf10e82d9fd8bfce3.tar.bz2
qemu-d3d250bddb3f6aa6c26e9dadf10e82d9fd8bfce3.zip
scsi: fix searching for an empty id
The conditions for detecting no free target or LUN were wrong. The LUN loop was followed by an "if" condition that is never true, because the loop is exited as soon as lun becomes equal to bus->info->max_lun, and never becomes greater than it. The target loop had a wrong condition (<= instead of <). Once this is fixed, the loop would fail in the same way as the LUN loop. The fix is to see whether scsi_device_find returned the device with the last (channel, target, LUN) pair, and fail if so. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--hw/scsi-bus.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 2cf2f0d8cf..2cb5a18da2 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -132,6 +132,10 @@ static int scsi_qdev_init(DeviceState *qdev)
error_report("bad scsi device id: %d", dev->id);
goto err;
}
+ if (dev->lun != -1 && dev->lun > bus->info->max_lun) {
+ error_report("bad scsi device lun: %d", dev->lun);
+ goto err;
+ }
if (dev->id == -1) {
int id = -1;
@@ -140,8 +144,8 @@ static int scsi_qdev_init(DeviceState *qdev)
}
do {
d = scsi_device_find(bus, dev->channel, ++id, dev->lun);
- } while (d && d->lun == dev->lun && id <= bus->info->max_target);
- if (id > bus->info->max_target) {
+ } while (d && d->lun == dev->lun && id < bus->info->max_target);
+ if (d && d->lun == dev->lun) {
error_report("no free target");
goto err;
}
@@ -151,14 +155,15 @@ static int scsi_qdev_init(DeviceState *qdev)
do {
d = scsi_device_find(bus, dev->channel, dev->id, ++lun);
} while (d && d->lun == lun && lun < bus->info->max_lun);
- if (lun > bus->info->max_lun) {
+ if (d && d->lun == lun) {
error_report("no free lun");
goto err;
}
dev->lun = lun;
} else {
d = scsi_device_find(bus, dev->channel, dev->id, dev->lun);
- if (dev->lun == d->lun && dev != d) {
+ assert(d);
+ if (d->lun == dev->lun && dev != d) {
qdev_free(&d->qdev);
}
}
@@ -217,7 +222,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
int res = 0, unit;
loc_push_none(&loc);
- for (unit = 0; unit < bus->info->max_target; unit++) {
+ for (unit = 0; unit <= bus->info->max_target; unit++) {
dinfo = drive_get(IF_SCSI, bus->busnr, unit);
if (dinfo == NULL) {
continue;