James - Can you ack or comment? Allow REPORT LUN scanning even if LUN 0 reports a peripheral qualifier of 3 (effectively no storage is available on LUN 0). Similar patch I previously posted: http://marc.theaimsgroup.com/?l=linux-scsi&m=110297733824960&w=2 There is also Hannes patch, it leaves LUN 0 available for use via user space, for compatibility it likely requires that it stay visible in the future: http://marc.theaimsgroup.com/?l=linux-scsi&m=111692497200507&w=2 Hannes' patch also causes a lot of extra vSCSI devices to show up on some platforms :) Signed-off-by: Patrick Mansfield <patmans@xxxxxxxxxx> diff -uprN -X /home/patman/dontdiff scsi-misc-2.6.git/drivers/scsi/scsi_scan.c lun0-scsi-misc-2.6.git/drivers/scsi/scsi_scan.c --- scsi-misc-2.6.git/drivers/scsi/scsi_scan.c 2005-08-16 15:02:20.000000000 -0700 +++ lun0-scsi-misc-2.6.git/drivers/scsi/scsi_scan.c 2005-08-30 14:59:15.000000000 -0700 @@ -64,14 +64,14 @@ * SCSI_SCAN_NO_RESPONSE: no valid response received from the target, this * includes allocation or general failures preventing IO from being sent. * - * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is available + * SCSI_SCAN_LUN_IGNORED: target responded, but no device is available * on the given LUN. * * SCSI_SCAN_LUN_PRESENT: target responded, and a device is available on a * given LUN. */ #define SCSI_SCAN_NO_RESPONSE 0 -#define SCSI_SCAN_TARGET_PRESENT 1 +#define SCSI_SCAN_LUN_IGNORED 1 #define SCSI_SCAN_LUN_PRESENT 2 static char *scsi_null_device_strs = "nullnullnullnull"; @@ -578,7 +578,7 @@ static void scsi_probe_lun(struct scsi_r /* * The scanning code needs to know the scsi_level, even if no - * device is attached at LUN 0 (SCSI_SCAN_TARGET_PRESENT) so + * device is attached at LUN 0 (SCSI_SCAN_LUN_IGNORED) so * non-zero LUNs can be scanned. */ sdev->scsi_level = inq_result[2] & 0x07; @@ -769,6 +769,19 @@ static int scsi_add_lun(struct scsi_devi return SCSI_SCAN_LUN_PRESENT; } +/* + * scsi_scan_remove: Helper funciton to free up sdev's that are not added + * as sys devices. That is, we never call scsi_probe_and_add_lun for these + * sdev's. + */ +static void scsi_scan_remove(struct scsi_device *sdev) +{ + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + transport_destroy_device(&sdev->sdev_gendev); + put_device(&sdev->sdev_gendev); +} + /** * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it * @starget: pointer to target device structure @@ -783,8 +796,10 @@ static int scsi_add_lun(struct scsi_devi * * Return: * SCSI_SCAN_NO_RESPONSE: could not allocate or setup a Scsi_Device - * SCSI_SCAN_TARGET_PRESENT: target responded, but no device is - * attached at the LUN + * SCSI_SCAN_LUN_IGNORED: target responded, but no device is + * attached at the LUN. The sdev is never made visible, and must + * be freed by the caller via scsi_scan_remove(). This way, LUN 0 + * is avaiable for use with the REPORT LUN command. * SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, @@ -853,7 +868,7 @@ static int scsi_probe_and_add_lun(struct SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: peripheral qualifier of 3," " no device added\n")); - res = SCSI_SCAN_TARGET_PRESENT; + res = SCSI_SCAN_LUN_IGNORED; goto out_free_result; } @@ -872,17 +887,13 @@ static int scsi_probe_and_add_lun(struct out_free_sreq: scsi_release_request(sreq); out_free_sdev: - if (res == SCSI_SCAN_LUN_PRESENT) { + if ((res == SCSI_SCAN_LUN_PRESENT) || (res == SCSI_SCAN_LUN_IGNORED)) { if (sdevp) { scsi_device_get(sdev); *sdevp = sdev; } - } else { - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); - transport_destroy_device(&sdev->sdev_gendev); - put_device(&sdev->sdev_gendev); - } + } else + scsi_scan_remove(sdev); out: return res; } @@ -1228,7 +1239,8 @@ static int scsi_report_lun_scan(struct s " from %s lun %d while scanning, scan" " aborted\n", devname, lun); break; - } + } else if (res == SCSI_SCAN_LUN_IGNORED) + scsi_scan_remove(sdev); } } @@ -1262,6 +1274,8 @@ struct scsi_device *__scsi_add_device(st if (scsi_host_scan_allowed(shost)) { res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); + if (res == SCSI_SCAN_LUN_IGNORED) + scsi_scan_remove(sdev); if (res != SCSI_SCAN_LUN_PRESENT) sdev = ERR_PTR(-ENODEV); } @@ -1334,7 +1348,8 @@ void scsi_scan_target(struct device *par /* * Scan for a specific host/chan/id/lun. */ - scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL); + res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, + rescan, NULL); goto out_reap; } @@ -1342,8 +1357,10 @@ void scsi_scan_target(struct device *par * Scan LUN 0, if there is some response, scan further. Ideally, we * would not configure LUN 0 until all LUNs are scanned. */ - res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, NULL); - if (res == SCSI_SCAN_LUN_PRESENT) { + res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, + NULL); + WARN_ON(!sdev && res != SCSI_SCAN_NO_RESPONSE); + if (sdev && res != SCSI_SCAN_NO_RESPONSE) if (scsi_report_lun_scan(sdev, bflags, rescan) != 0) /* * The REPORT LUN did not scan the target, @@ -1351,20 +1368,12 @@ void scsi_scan_target(struct device *par */ scsi_sequential_lun_scan(starget, bflags, res, sdev->scsi_level, rescan); - } else if (res == SCSI_SCAN_TARGET_PRESENT) { - /* - * There's a target here, but lun 0 is offline so we - * can't use the report_lun scan. Fall back to a - * sequential lun scan with a bflags of SPARSELUN and - * a default scsi level of SCSI_2 - */ - scsi_sequential_lun_scan(starget, BLIST_SPARSELUN, - SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan); - } if (sdev) scsi_device_put(sdev); out_reap: + if (res == SCSI_SCAN_LUN_IGNORED) + scsi_scan_remove(sdev); /* now determine if the target has any children at all * and if not, nuke it */ scsi_target_reap(starget); @@ -1540,4 +1549,3 @@ void scsi_free_host_dev(struct scsi_devi put_device(&sdev->sdev_gendev); } EXPORT_SYMBOL(scsi_free_host_dev); - - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html