]> git.proxmox.com Git - qemu.git/commitdiff
scsi: fix searching for an empty id
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 15 Feb 2012 08:22:54 +0000 (09:22 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 24 Feb 2012 13:54:51 +0000 (14:54 +0100)
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>
hw/scsi-bus.c

index 2cf2f0d8cf935ab81813d22ad05c438f690449ea..2cb5a18da225fa0bbbe10786c18bf1b98dde8cde 100644 (file)
@@ -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;