Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH] 2.4.19 scsi_rescan patch (2nd pass)
@ 2002-10-02 14:52 Cress, Andrew R
  2002-10-02 15:34 ` James Bottomley
  0 siblings, 1 reply; 8+ messages in thread
From: Cress, Andrew R @ 2002-10-02 14:52 UTC (permalink / raw)
  To: linux-scsi

Folks,

Here is a 2nd pass at a patch to do a scsi rescan so that hot-inserted scsi
disks can automatically be recognized.  It includes some recommended
changes/cleanup from Patrick and Mike.

Andy Cress

---------------
--- linux-2.4.19-orig/drivers/scsi/hosts.h	Mon Feb 25 14:38:04 2002
+++ linux-2.4.19/drivers/scsi/hosts.h	Wed Oct  2 09:33:02 2002
@@ -418,6 +418,8 @@
      */
     unsigned some_device_starved:1;
    
+    unsigned init_done:1;
+    unsigned char need_scan; 
     void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
 
     /*
--- linux-2.4.19-orig/drivers/scsi/scsi.c	Fri Aug  2 20:39:44 2002
+++ linux-2.4.19/drivers/scsi/scsi.c	Wed Oct  2 09:33:02 2002
@@ -1980,8 +1980,10 @@
 			for (SDpnt = shpnt->host_queue; SDpnt; SDpnt =
SDpnt->next)
 				if (SDpnt->host->hostt == tpnt) {
 					for (sdtpnt = scsi_devicelist;
sdtpnt; sdtpnt = sdtpnt->next)
-						if (sdtpnt->attach)
+						if (sdtpnt->attach) {
 							(*sdtpnt->attach)
(SDpnt);
+							SDpnt->need_attach =
FALSE;
+						}
 					if (SDpnt->attached) {
 
scsi_build_commandblocks(SDpnt);
 						if (0 ==
SDpnt->has_cmdblocks)
@@ -2003,6 +2005,9 @@
 				(*sdtpnt->finish) ();
 			}
 		}
+		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
+			shpnt->init_done = 1;
+		}
 	}
 #if defined(USE_STATIC_SCSI_MEMORY)
 	printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n",
@@ -2296,8 +2301,10 @@
 		     SDpnt = SDpnt->next) {
 			SDpnt->attached += SDpnt->detected;
 			SDpnt->detected = 0;
-			if (tpnt->attach)
+			if (tpnt->attach) {
 				(*tpnt->attach) (SDpnt);
+				SDpnt->need_attach = FALSE;
+			}
 			/*
 			 * If this driver attached to the device, and don't
have any
 			 * command blocks for this device, allocate some.
--- linux-2.4.19-orig/drivers/scsi/scsi.h	Fri Aug  2 20:39:44 2002
+++ linux-2.4.19/drivers/scsi/scsi.h	Wed Oct  2 09:33:02 2002
@@ -617,6 +617,7 @@
 	unsigned remap:1;	/* support remapping  */
 	unsigned starved:1;	/* unable to process commands because
 				   host busy */
+	unsigned need_attach:1; /* newly rescanned, need to attach device */
 
 	// Flag to allow revalidate to succeed in sd_open
 	int allow_revalidate;
--- linux-2.4.19-orig/drivers/scsi/scsi_lib.c	Fri Aug  2 20:39:44 2002
+++ linux-2.4.19/drivers/scsi/scsi_lib.c	Wed Oct  2 09:40:15 2002
@@ -5,6 +5,8 @@
  *      Initial versions: Eric Youngdale (eric@andante.org).
  *                        Based upon conversations with large numbers
  *                        of people at Linux Expo.
+ *      10/02/2002 - Andrew.R.Cress@intel.com, added scsi_rescan to
+ *                     automatically recognize hot-inserted disks
  */
 
 /*
@@ -819,6 +821,68 @@
 	return NULL;
 }
 
+void scsi_rescan(struct Scsi_Host *SHpnt, unsigned int channel)
+{
+	Scsi_Device *SDpnt;
+	struct Scsi_Device_Template *sdtpnt;
+	int out_of_space = 0;
+	int new_dev = 0;
+	int fdidattach;
+
+	/* 
+	 * Do scan_scsis here.  This generates the Scsi_Devices entries.
+	 * Since SHpnt->init_done, if devices already exist, skip them. 
+	 */
+	scan_scsis(SHpnt, 0, channel, 0, 0);
+
+	for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
+		if (sdtpnt->init && sdtpnt->dev_noticed)
+			(*sdtpnt->init) ();
+	}
+
+	/* Next we create the Scsi_Cmnd structures for new devices */
+	for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
+		fdidattach = 0;
+		if (SDpnt->host->host_no == SHpnt->host_no) {
+			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt =
sdtpnt->next) {
+				/* 
+				 * attached can be set here for the new one,
+				 * so also check if queue_depth has been 
+				 * set to a normal value yet (> 2).
+				 */
+				if (SDpnt->need_attach && sdtpnt->attach) {
+					/*Note /dev/sd* maj=8, /dev/sg*
maj=21*/
+					(*sdtpnt->attach) (SDpnt);
+					fdidattach = 1;
+			  	} /*endif need_attach*/
+			} /*end sdtpnt loop*/
+			if (fdidattach) {
+			    fdidattach = 0;
+			    new_dev++;
+                	    if (SHpnt->select_queue_depths != NULL) {
+				(SHpnt->select_queue_depths) (SHpnt,
SHpnt->host_queue);
+			    }
+			    if (SDpnt->need_attach && SDpnt->attached) {
+				SDpnt->need_attach = FALSE;
+				scsi_build_commandblocks(SDpnt);
+				if (0 == SDpnt->has_cmdblocks)
+					out_of_space = 1;
+			    }
+			}
+		} /*endif match host_no */
+	}  /*end SDpnt loop*/
+
+	/* May have added some devices, so resize the DMA pool. */
+	if (new_dev > 0 && !out_of_space) scsi_resize_dma_pool();
+
+	for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
+		if (sdtpnt->finish && sdtpnt->nr_dev) 
+			(*sdtpnt->finish) (); 
+	}
+	printk("scsi_rescan: %d new devices added\n",new_dev);
+
+} /*end scsi_rescan*/
+
 /*
  * Function:    scsi_request_fn()
  *
@@ -919,6 +983,17 @@
 				spin_lock_irq(&io_request_lock);
 				continue;
 			}
+
+			if (!in_interrupt()) {
+			   /* Check if we need to rescan after a reset.
ARC*/
+			   if (SDpnt->host->need_scan == 1) {
+				SDpnt->host->need_scan = 2;
+				spin_unlock_irq(&io_request_lock);
+				scsi_rescan(SDpnt->host,SDpnt->channel);
+				spin_lock_irq(&io_request_lock);
+				SDpnt->host->need_scan = 0;
+			   }
+			}
 		}
 
 		/*
@@ -1176,6 +1251,11 @@
 			SDloop->was_reset = 1;
 			SDloop->expecting_cc_ua = 1;
 		}
+	}
+	if (SHpnt->init_done == 1 && SHpnt->need_scan == 0) {
+		SHpnt->need_scan = 1; 
+		printk("scsi_report_bus_reset: scsi%d, channel %d
need_scan\n",
+			SHpnt->host_no,channel);
 	}
 }
 
--- linux-2.4.19-orig/drivers/scsi/scsi_scan.c	Fri Aug  2 20:39:44 2002
+++ linux-2.4.19/drivers/scsi/scsi_scan.c	Wed Oct  2 09:33:02 2002
@@ -287,6 +287,28 @@
 }
 
 /*
+ * scsi_dev_skip
+ * Returns 1 if there was already a device on this host at the same
+ * channel/dev/lun, indicating that the caller should skip this one.
+ * Make sure to not match the new/temp device created for the scan 
+ * (sdnew).  sdpnt->attached is often already set here on the new 
+ * device(s), so we can't use that. 
+ */
+static int
+scsi_dev_skip(struct Scsi_Host *shpnt, uint channel, uint dev, uint lun,
+              Scsi_Device *sdnew)
+{
+	Scsi_Device *sdpnt;
+	for (sdpnt = shpnt->host_queue; sdpnt; sdpnt = sdpnt->next)
+		if (sdpnt != sdnew && (sdpnt->host == shpnt) &&  
+		    (sdpnt->id == dev) && (sdpnt->lun == lun) &&
+		    (sdpnt->channel == channel)) {
+			return 1;
+		}
+	return 0;
+}  /*end scsi_dev_skip*/
+
+/*
  *  Detecting SCSI devices :
  *  We scan all present host adapter's busses,  from ID 0 to ID (max_id).
  *  We use the INQUIRY command, determine device type, and pass the ID /
@@ -380,6 +402,8 @@
 		lun = hlun;
 		if (lun >= shpnt->max_lun)
 			goto leave;
+		if (shpnt->init_done && 
+		    scsi_dev_skip(shpnt,hchannel,hid,hlun,SDpnt)) goto
leave;
 		if ((0 == lun) || (lun > 7))
 			lun0_sl = SCSI_3; /* actually don't care for 0 ==
lun */
 		else
@@ -402,6 +426,7 @@
 			for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt =
sdtpnt->next) {
 				if (sdtpnt->attach) {
 					(*sdtpnt->attach) (oldSDpnt);
+					oldSDpnt->need_attach = FALSE;
 					if (oldSDpnt->attached) {
 
scsi_build_commandblocks(oldSDpnt);
 						if (0 ==
oldSDpnt->has_cmdblocks) {
@@ -445,6 +470,9 @@
 						/* don't probe further for
luns > 7 for targets <= SCSI_2 */
 						if ((lun0_sl < SCSI_3) &&
(lun > 7))
 							break;
+						if (shpnt->init_done &&
+
scsi_dev_skip(shpnt,channel,dev,lun, SDpnt)) 
+                                                	continue; /* ARC*/
 
 						if
(!scan_scsis_single(channel, order_dev, lun, lun0_sl,
 
&max_dev_lun, &sparse_lun, &SDpnt, shpnt,
@@ -528,6 +556,10 @@
 	extern devfs_handle_t scsi_devfs_handle;
 	int scsi_level;
 
+	if (SDpnt == NULL) {
+		printk("scan_scsis_single: SDpnt = NULL\n");
+		return 0;
+	}
 	SDpnt->host = shpnt;
 	SDpnt->id = dev;
 	SDpnt->lun = lun;
@@ -559,7 +591,8 @@
 	 * devices (and TEST_UNIT_READY to poll for media change). - Paul G.
 	 */
 
-	SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n"));
+	SCSI_LOG_SCAN_BUS(3, printk("scsi_scan: [%d:%d:%d:%d] performing
INQUIRY\n",
+				shpnt->host_no, channel, dev, lun));
 	/*
 	 * Build an INQUIRY command block.
 	 */
@@ -587,12 +620,19 @@
 	 * for media change conditions here, so cannot require zero result.
 	 */
 	if (SRpnt->sr_result) {
+		int attn_ok = 0;
 		if ((driver_byte(SRpnt->sr_result) & DRIVER_SENSE) != 0 &&
-		    (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION &&
-		    SRpnt->sr_sense_buffer[12] == 0x28 &&
+		    (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
+		  if (SRpnt->sr_sense_buffer[12] == 0x28 &&
 		    SRpnt->sr_sense_buffer[13] == 0) {
 			/* not-ready to ready transition - good */
-		} else {
+			attn_ok = 1;
+		  } else if (SRpnt->sr_sense_buffer[12] == 0x29) {
+			/* 06/29/xx = reset occurred, but ok now - ARC */
+			attn_ok = 1;
+		  } 
+		}
+		if (!attn_ok) {
 			/* assume no peripheral if any other sort of error
*/
 			scsi_release_request(SRpnt);
 			return 0;
@@ -691,9 +731,12 @@
 
 	for (sdtpnt = scsi_devicelist; sdtpnt;
 	     sdtpnt = sdtpnt->next)
-		if (sdtpnt->detect)
+		if (sdtpnt->detect) {
 			SDpnt->attached +=
 			    (*sdtpnt->detect) (SDpnt);
+			/* did detect, but still need attach */
+			SDpnt->need_attach = TRUE;  
+		}
 
 	SDpnt->scsi_level = scsi_result[2] & 0x07;
 	if (SDpnt->scsi_level >= 2 ||

^ permalink raw reply	[flat|nested] 8+ messages in thread
* RE: [PATCH] 2.4.19 scsi_rescan patch (2nd pass)
@ 2002-10-02 16:26 Cress, Andrew R
  2002-10-02 16:29 ` James Bottomley
  0 siblings, 1 reply; 8+ messages in thread
From: Cress, Andrew R @ 2002-10-02 16:26 UTC (permalink / raw)
  To: 'James Bottomley'; +Cc: linux-scsi

James,

I had been trying to do that with a user-level daemon I've written
(sgraidmon at scsirastools.sf.net), but I can't rescan from user level
because the new devices aren't attached to any /dev, so the user-level can't
detect that a new device has been inserted, and it doesn't have any way to
detect which device it might be.  

Previous development has assumed that some administrator "knows" what the
new device is and that it has been inserted, in order to invoke a hotplug
function.  My use case is to make software RAID more like hardware RAID,
where a service tech inserts the disk and walks away, and the software raid
(OS & daemon) detects it and handles it automatically.

Andy

-----Original Message-----
From: James Bottomley [mailto:James.Bottomley@steeleye.com] 
Sent: Wednesday, October 02, 2002 11:35 AM
To: Cress, Andrew R
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH] 2.4.19 scsi_rescan patch (2nd pass) 

andrew.r.cress@intel.com said:
> Here is a 2nd pass at a patch to do a scsi rescan so that hot-inserted
> scsi disks can automatically be recognized.  It includes some
> recommended changes/cleanup from Patrick and Mike. 

Is there a really good reason we can't use the hotplug infrastructure for
this 
and scan from user level?  I know the 2.4 hotplug is less well developed
than 
2.5, but I believe it will work well enough for this.

If you go the hotplug route, all we need is a hook to trigger the SCSI
hotplug 
event.

James


^ permalink raw reply	[flat|nested] 8+ messages in thread
* RE: [PATCH] 2.4.19 scsi_rescan patch (2nd pass)
@ 2002-10-02 16:40 Cress, Andrew R
  2002-10-02 16:56 ` Doug Ledford
  0 siblings, 1 reply; 8+ messages in thread
From: Cress, Andrew R @ 2002-10-02 16:40 UTC (permalink / raw)
  To: 'James Bottomley', Cress, Andrew R; +Cc: linux-scsi

James,

A user-space hotplug event can't be guaranteed to have enough information in
all cases.
Possible cases:
  1) Administrator "knows" and manually issues a hot-plug command. 
  2) A daemon detects a SAF-TE or SES event by slot number.  
     Not sure if we can really determine what we need from just a slot
number?
  3) Other external disk enclosure (JBOD) that doesn't expose a 
     SAF-TE or SES interface.
     This case is out in the cold without the kernel-level rescan.

I'm disregarding case (1), since my target customer environment won't
tolerate the manual step.

Andy

-----Original Message-----
From: James Bottomley [mailto:James.Bottomley@steeleye.com] 
Sent: Wednesday, October 02, 2002 12:29 PM
To: Cress, Andrew R
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH] 2.4.19 scsi_rescan patch (2nd pass) 

andrew.r.cress@intel.com said:
> I had been trying to do that with a user-level daemon I've written
> (sgraidmon at scsirastools.sf.net), but I can't rescan from user level
> because the new devices aren't attached to any /dev, so the user-level
> can't detect that a new device has been inserted, and it doesn't have
> any way to detect which device it might be.   

Right, that's why the hotplug event has to carry enough information to allow

the script to identify what needs to be scanned (i.e. SCSI hostadapter
number 
and PUN if possible). the scsi add-single-device mechanism can then be used
to 
do the attachment (and scanning).

James




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2002-10-02 17:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-10-02 14:52 [PATCH] 2.4.19 scsi_rescan patch (2nd pass) Cress, Andrew R
2002-10-02 15:34 ` James Bottomley
2002-10-02 16:49   ` Doug Ledford
  -- strict thread matches above, loose matches on Subject: below --
2002-10-02 16:26 Cress, Andrew R
2002-10-02 16:29 ` James Bottomley
2002-10-02 16:40 Cress, Andrew R
2002-10-02 16:56 ` Doug Ledford
2002-10-02 17:23   ` Patrick Mansfield

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox