scsi: Add intermediate STARGET_REMOVE state to scsi_target_state
[cascardo/linux.git] / drivers / scsi / scsi_scan.c
index 97074c9..e0a78f5 100644 (file)
@@ -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;
 
@@ -316,6 +319,7 @@ static void scsi_target_destroy(struct scsi_target *starget)
        struct Scsi_Host *shost = dev_to_shost(dev->parent);
        unsigned long flags;
 
+       BUG_ON(starget->state == STARGET_DEL);
        starget->state = STARGET_DEL;
        transport_destroy_device(dev);
        spin_lock_irqsave(shost->host_lock, flags);
@@ -1040,7 +1044,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 +1060,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 +1075,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 +1211,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 +1307,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 +1553,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 +1611,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 +1624,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 +1648,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 +1680,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 +1860,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;