Re: [2.6.14-rc1] sym scsi boot hang

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 14 Sep 2005, Anton Blanchard wrote:

> Hi,
> 
> > If that's the cause, it's probably a double down of the host scan
> > semaphore somewhere in the code.  alt-sysrq-t should work in this case,
> > can you get a stack trace of the blocked process?
> 
> It appears to be this patch:
> 
>   [SCSI] SCSI core: fix leakage of scsi_cmnd's
> 
>   From:         Alan Stern <[email protected]>

> And in particular it looks like the scsi_unprep_request in
> scsi_queue_insert is causing it. The following patch fixes the boot
> problems on the vscsi machine:

In general the scsi_unprep_request routine is correct and needs to be
there.  The one part that might be questionable is the assignment to
req->special.  It may turn out that the real solution is to have
scsi_execute set req->special to NULL; I assumed it would be NULL already
but perhaps I was wrong.

(James, I see a possible problem with scsi_insert_special_req.  It adds to
the queue a request with REQ_DONTPREP set.  How can such a request, with
no associated scsi_cmnd, ever work?  Also, won't scsi_end_request and 
__scsi_release_request end up putting the same scsi_command twice?)

Here is a patch that addresses the first problem and fixes up a few other
loose ends.  Please see if it helps.

Alan Stern



Index: usb-2.6/drivers/scsi/scsi_lib.c
===================================================================
--- usb-2.6.orig/drivers/scsi/scsi_lib.c
+++ usb-2.6/drivers/scsi/scsi_lib.c
@@ -116,7 +116,13 @@ static void scsi_unprep_request(struct r
 	struct scsi_cmnd *cmd = req->special;
 
 	req->flags &= ~REQ_DONTPREP;
-	req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+	req->special = NULL;
+	if (req->flags & REQ_SPECIAL) {
+		struct scsi_request *sreq = cmd->sc_request;
+
+		if (sreq->sr_magic == SCSI_REQ_MAGIC)
+			req->special = sreq;
+	}
 
 	scsi_release_buffers(cmd);
 	scsi_put_command(cmd);
@@ -343,6 +349,7 @@ int scsi_execute(struct scsi_device *sde
 	req->sense_len = 0;
 	req->timeout = timeout;
 	req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
+	req->special = NULL;
 
 	/*
 	 * head injection *required* here otherwise quiesce won't work
@@ -1072,9 +1079,6 @@ static int scsi_init_io(struct scsi_cmnd
 	printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
 			req->current_nr_sectors);
 
-	/* release the command and kill it */
-	scsi_release_buffers(cmd);
-	scsi_put_command(cmd);
 	return BLKPREP_KILL;
 }
 
@@ -1176,13 +1180,13 @@ static int scsi_prep_fn(struct request_q
 	if (req->flags & REQ_SPECIAL && req->special) {
 		struct scsi_request *sreq = req->special;
 
-		if (sreq->sr_magic == SCSI_REQ_MAGIC) {
-			cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC);
-			if (unlikely(!cmd))
-				goto defer;
-			scsi_init_cmd_from_req(cmd, sreq);
-		} else
-			cmd = req->special;
+		if (sreq->sr_magic != SCSI_REQ_MAGIC)
+			printk(KERN_ERR "invalid sr_magic in %s\n",
+					__FUNCTION__);
+		cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC);
+		if (unlikely(!cmd))
+			goto defer;
+		scsi_init_cmd_from_req(cmd, sreq);
 	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 
 		if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
@@ -1194,17 +1198,14 @@ static int scsi_prep_fn(struct request_q
 			       sdev->host->host_no, sdev->id, sdev->lun);
 			goto kill;
 		}
-			
 			
 		/*
 		 * Now try and find a command block that we can use.
 		 */
-		if (!req->special) {
-			cmd = scsi_get_command(sdev, GFP_ATOMIC);
-			if (unlikely(!cmd))
-				goto defer;
-		} else
-			cmd = req->special;
+		cmd = scsi_get_command(sdev, GFP_ATOMIC);
+		if (unlikely(!cmd))
+			goto defer;
+		cmd->sc_request = NULL;
 		
 		/* pull a tag out of the request if we have one */
 		cmd->tag = req->tag;
@@ -1250,7 +1251,7 @@ static int scsi_prep_fn(struct request_q
 		ret = scsi_init_io(cmd);
 		switch(ret) {
 		case BLKPREP_KILL:
-			/* BLKPREP_KILL return also releases the command */
+			scsi_unprep_request(req);
 			goto kill;
 		case BLKPREP_DEFER:
 			goto defer;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux