Skip to content

Commit

Permalink
scsi: disable automatic target scan
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Ewan D. Milne <[email protected]>
Tested-by: Laurence Oberman <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
hreinecke authored and martinkpetersen committed Apr 11, 2016
1 parent 216fad9 commit 1d64508
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 28 deletions.
2 changes: 1 addition & 1 deletion drivers/infiniband/ulp/srp/ib_srp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2819,7 +2819,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
spin_unlock(&host->target_lock);

scsi_scan_target(&target->scsi_host->shost_gendev,
0, target->scsi_id, SCAN_WILD_CARD, 0);
0, target->scsi_id, SCAN_WILD_CARD, SCSI_SCAN_INITIAL);

if (srp_connected_ch(target) < target->ch_count ||
target->qp_in_error) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/message/fusion/mptspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ static void mpt_work_wrapper(struct work_struct *work)
}
shost_printk(KERN_INFO, shost, MYIOC_s_FMT
"Integrated RAID detects new device %d\n", ioc->name, disk);
scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);
scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, SCSI_SCAN_RESCAN);
}


Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/scsi/zfcp_unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);

if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1);
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun,
SCSI_SCAN_RESCAN);
}

static void zfcp_unit_scsi_scan_work(struct work_struct *work)
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/scsi_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ extern void scsi_exit_procfs(void);
extern char scsi_scan_type[];
extern int scsi_complete_async_scans(void);
extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
unsigned int, u64, int);
unsigned int, u64, enum scsi_scan_mode);
extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_rescan_device(struct device *);

Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/scsi_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
if (shost->transportt->user_scan)
error = shost->transportt->user_scan(shost, channel, id, lun);
else
error = scsi_scan_host_selected(shost, channel, id, lun, 1);
error = scsi_scan_host_selected(shost, channel, id, lun,
SCSI_SCAN_MANUAL);
scsi_host_put(shost);
return error;
}
Expand Down
44 changes: 30 additions & 14 deletions drivers/scsi/scsi_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand All @@ -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)));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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();
Expand All @@ -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;

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/scsi/scsi_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
if (shost->transportt->user_scan)
res = shost->transportt->user_scan(shost, channel, id, lun);
else
res = scsi_scan_host_selected(shost, channel, id, lun, 1);
res = scsi_scan_host_selected(shost, channel, id, lun,
SCSI_SCAN_MANUAL);
return res;
}

Expand Down
6 changes: 4 additions & 2 deletions drivers/scsi/scsi_transport_fc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2110,7 +2110,8 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun)
if ((channel == rport->channel) &&
(id == rport->scsi_target_id)) {
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_scan_target(&rport->dev, channel, id, lun, 1);
scsi_scan_target(&rport->dev, channel, id, lun,
SCSI_SCAN_MANUAL);
return;
}
}
Expand Down Expand Up @@ -3277,7 +3278,8 @@ fc_scsi_scan_rport(struct work_struct *work)
(rport->roles & FC_PORT_ROLE_FCP_TARGET) &&
!(i->f->disable_target_scan)) {
scsi_scan_target(&rport->dev, rport->channel,
rport->scsi_target_id, SCAN_WILD_CARD, 1);
rport->scsi_target_id, SCAN_WILD_CARD,
SCSI_SCAN_RESCAN);
}

spin_lock_irqsave(shost->host_lock, flags);
Expand Down
5 changes: 4 additions & 1 deletion drivers/scsi/scsi_transport_iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,7 @@ struct iscsi_scan_data {
unsigned int channel;
unsigned int id;
u64 lun;
enum scsi_scan_mode rescan;
};

static int iscsi_user_scan_session(struct device *dev, void *data)
Expand Down Expand Up @@ -1819,7 +1820,7 @@ static int iscsi_user_scan_session(struct device *dev, void *data)
(scan_data->id == SCAN_WILD_CARD ||
scan_data->id == id))
scsi_scan_target(&session->dev, 0, id,
scan_data->lun, 1);
scan_data->lun, scan_data->rescan);
}

user_scan_exit:
Expand All @@ -1836,6 +1837,7 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
scan_data.channel = channel;
scan_data.id = id;
scan_data.lun = lun;
scan_data.rescan = SCSI_SCAN_MANUAL;

return device_for_each_child(&shost->shost_gendev, &scan_data,
iscsi_user_scan_session);
Expand All @@ -1852,6 +1854,7 @@ static void iscsi_scan_session(struct work_struct *work)
scan_data.channel = 0;
scan_data.id = SCAN_WILD_CARD;
scan_data.lun = SCAN_WILD_CARD;
scan_data.rescan = SCSI_SCAN_RESCAN;

iscsi_user_scan_session(&session->dev, &scan_data);
atomic_dec(&ihost->nr_scans);
Expand Down
7 changes: 4 additions & 3 deletions drivers/scsi/scsi_transport_sas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1614,7 +1614,8 @@ int sas_rphy_add(struct sas_rphy *rphy)
else
lun = 0;

scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0);
scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun,
SCSI_SCAN_INITIAL);
}

return 0;
Expand Down Expand Up @@ -1739,8 +1740,8 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,

if ((channel == SCAN_WILD_CARD || channel == 0) &&
(id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
scsi_scan_target(&rphy->dev, 0,
rphy->scsi_target_id, lun, 1);
scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id,
lun, SCSI_SCAN_MANUAL);
}
}
mutex_unlock(&sas_host->lock);
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/snic/snic_disc.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ snic_scsi_scan_tgt(struct work_struct *work)
tgt->channel,
tgt->scsi_tgt_id,
SCAN_WILD_CARD,
1);
SCSI_SCAN_RESCAN);

spin_lock_irqsave(shost->host_lock, flags);
tgt->flags &= ~SNIC_TGT_SCAN_PENDING;
Expand Down
9 changes: 8 additions & 1 deletion include/scsi/scsi_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ enum scsi_device_state {
SDEV_CREATED_BLOCK, /* same as above but for created devices */
};

enum scsi_scan_mode {
SCSI_SCAN_INITIAL = 0,
SCSI_SCAN_RESCAN,
SCSI_SCAN_MANUAL,
};

enum scsi_device_event {
SDEV_EVT_MEDIA_CHANGE = 1, /* media has changed */
SDEV_EVT_INQUIRY_CHANGE_REPORTED, /* 3F 03 UA reported */
Expand Down Expand Up @@ -391,7 +397,8 @@ extern void scsi_device_resume(struct scsi_device *sdev);
extern void scsi_target_quiesce(struct scsi_target *);
extern void scsi_target_resume(struct scsi_target *);
extern 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);
extern void scsi_target_reap(struct scsi_target *);
extern void scsi_target_block(struct device *);
extern void scsi_target_unblock(struct device *, enum scsi_device_state);
Expand Down

0 comments on commit 1d64508

Please sign in to comment.