From: "Ewan D. Milne" <emilne@xxxxxxxxxx> This patch adds the capability to configure the kernel to automatically remove LUNs when a rescan of a SCSI target finds that LUNs that were previously reported are no longer being reported. This is only done when a target is scanned using REPORT LUNS, to avoid removing LUNs due to transport errors (in other words, the target must be accessible). Signed-off-by: Ewan D. Milne <emilne@xxxxxxxxxx> --- drivers/scsi/Kconfig | 8 +++++++ drivers/scsi/scsi_scan.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 5d1e614..9642c87 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -292,6 +292,14 @@ config SCSI_ENHANCED_UA primarily useful when storage arrays that can be reconfigured are attached to the system, otherwise you can say N here. +config SCSI_AUTOMATIC_LUN_REMOVAL + bool "Automatic LUN removal" + depends on SCSI + help + If you want LUNs to be automatically removed when a SCSI target + is rescanned and the REPORT LUNS result indicates that LUNs are + no longer present, say Y. Otherwise, say N. + menu "SCSI Transports" depends on SCSI diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1bbbc43..a0d0d97 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1318,6 +1318,11 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, struct scsi_device *sdev; struct Scsi_Host *shost = dev_to_shost(&starget->dev); int ret = 0; +#ifdef CONFIG_SCSI_AUTOMATIC_LUN_REMOVAL + unsigned long flags; + struct scsi_device *sdev_i; + bool found; +#endif /* * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. @@ -1490,6 +1495,55 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, } } +#ifdef CONFIG_SCSI_AUTOMATIC_LUN_REMOVAL + /* + * See if all of the LUNs that we know about on the target are + * still being reported in the REPORT LUNS data. If any are not, + * they have been removed from the target. Remove those LUNs. + * + * We only do this for REPORT LUNS scanning, because we do not + * want to remove LUNs if they are inaccessible due to a transport + * error. Here, the target has responded to a command. + */ +restart: + spin_lock_irqsave(shost->host_lock, flags); + list_for_each_entry(sdev_i, &starget->devices, same_target_siblings) { + /* + * Don't remove the sdev used for the REPORT LUNS command here. + * It will be removed at the end of the function if necessary. + */ + if (sdev_i == sdev) + continue; + if (sdev_i->sdev_state == SDEV_DEL) + continue; + found = 0; + for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { + lun = scsilun_to_int(lunp); + if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) + continue; + else if (lun > sdev->host->max_lun) + continue; + else if (lun == sdev_i->lun) { + found = 1; + break; + } + } + if (!found) { + spin_unlock_irqrestore(shost->host_lock, flags); + sdev_printk(KERN_INFO, sdev_i, + "LUN %d is no longer present, removing\n", + sdev_i->lun); + __scsi_remove_device(sdev_i); + /* + * Once the device has been removed, the iterator + * is no longer valid and we have to start again. + */ + goto restart; + } + } + spin_unlock_irqrestore(shost->host_lock, flags); +#endif + out_err: kfree(lun_data); out: -- 1.7.11.7 -- To unsubscribe from this list: 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