From 1d64508810d8d15867251c75a68d7250278ce2bd Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 17 Mar 2016 08:39:45 +0100 Subject: scsi: disable automatic target scan On larger installations it is useful to disable automatic LUN scanning, and only add the required LUNs via udev rules. This can speed up bootup dramatically. This patch introduces a new scan module parameter value 'manual', which works like 'none', but can be overridden by setting the 'rescan' value from scsi_scan_target to 'SCSI_SCAN_MANUAL'. And it updates all relevant callers to set the 'rescan' value to 'SCSI_SCAN_MANUAL' if invoked via the 'scan' option in sysfs. Signed-off-by: Hannes Reinecke Reviewed-by: Ewan D. Milne Tested-by: Laurence Oberman Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_scan.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers/scsi/scsi_scan.c') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 97074c91e328..6c8ad36560d1 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -96,10 +96,13 @@ MODULE_PARM_DESC(max_luns, #define SCSI_SCAN_TYPE_DEFAULT "sync" #endif -char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; +char scsi_scan_type[7] = SCSI_SCAN_TYPE_DEFAULT; -module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); -MODULE_PARM_DESC(scan, "sync, async or none"); +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(scan, "sync, async, manual, or none. " + "Setting to 'manual' disables automatic scanning, but allows " + "for manual device scan via the 'scan' sysfs attribute."); static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ + 18; @@ -1040,7 +1043,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * @lun: LUN of target device * @bflagsp: store bflags here if not NULL * @sdevp: probe the LUN corresponding to this scsi_device - * @rescan: if nonzero skip some code only needed on first scan + * @rescan: if not equal to SCSI_SCAN_INITIAL skip some code only + * needed on first scan * @hostdata: passed to scsi_alloc_sdev() * * Description: @@ -1055,7 +1059,8 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, u64 lun, int *bflagsp, - struct scsi_device **sdevp, int rescan, + struct scsi_device **sdevp, + enum scsi_scan_mode rescan, void *hostdata) { struct scsi_device *sdev; @@ -1069,7 +1074,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, */ sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { - if (rescan || !scsi_device_created(sdev)) { + if (rescan != SCSI_SCAN_INITIAL || !scsi_device_created(sdev)) { SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: device exists on %s\n", dev_name(&sdev->sdev_gendev))); @@ -1205,7 +1210,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, * Modifies sdevscan->lun. **/ static void scsi_sequential_lun_scan(struct scsi_target *starget, - int bflags, int scsi_level, int rescan) + int bflags, int scsi_level, + enum scsi_scan_mode rescan) { uint max_dev_lun; u64 sparse_lun, lun; @@ -1300,7 +1306,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * 1: could not scan with REPORT LUN **/ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, - int rescan) + enum scsi_scan_mode rescan) { char devname[64]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -1546,7 +1552,7 @@ void scsi_rescan_device(struct device *dev) EXPORT_SYMBOL(scsi_rescan_device); static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1604,7 +1610,10 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * @channel: channel to scan * @id: target id to scan * @lun: Specific LUN to scan or SCAN_WILD_CARD - * @rescan: passed to LUN scanning routines + * @rescan: passed to LUN scanning routines; SCSI_SCAN_INITIAL for + * no rescan, SCSI_SCAN_RESCAN to rescan existing LUNs, + * and SCSI_SCAN_MANUAL to force scanning even if + * 'scan=manual' is set. * * Description: * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, @@ -1614,13 +1623,17 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * sequential scan of LUNs on the target id. **/ void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, enum scsi_scan_mode rescan) { struct Scsi_Host *shost = dev_to_shost(parent); if (strncmp(scsi_scan_type, "none", 4) == 0) return; + if (rescan != SCSI_SCAN_MANUAL && + strncmp(scsi_scan_type, "manual", 6) == 0) + return; + mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1634,7 +1647,8 @@ void scsi_scan_target(struct device *parent, unsigned int channel, EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { uint order_id; @@ -1665,7 +1679,8 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, u64 lun, int rescan) + unsigned int id, u64 lun, + enum scsi_scan_mode rescan) { SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, "%s: <%u:%u:%llu>\n", @@ -1844,7 +1859,8 @@ void scsi_scan_host(struct Scsi_Host *shost) { struct async_scan_data *data; - if (strncmp(scsi_scan_type, "none", 4) == 0) + if (strncmp(scsi_scan_type, "none", 4) == 0 || + strncmp(scsi_scan_type, "manual", 6) == 0) return; if (scsi_autopm_get_host(shost) < 0) return; -- cgit v1.2.3