Re: [2.6.14-rc1] sym scsi boot hang

Alan Stern
2005-09-14T20:19:51Z

On Wed, 14 Sep 2005, James Bottomley wrote:

> OK, my fault. Your fix is almost correct .. I was going to do this
> eventually, honest, because there's no need to unprep and reprep a
> command that comes in through scsi_queue_insert().
>
> However, I decided to leave it in to exercise the scsi_unprep_request()
> path just to make sure it was working. What's happening, I think, is
> that we also use this path for retries. Since we kill and reget the
> command each time, the retries decrement is never seen, so we're
> retrying forever.
>
> This should be the correct reversal.

Then shouldn't you also avoid unprepping and reprepping a command that is
deferred because the host isn't ready?

And isn't it necessary to make sure that req->special is NULL when
submitting a special request with no scsi_request, and that
cmd->sc_request is NULL when associating a command block to a special
request with no scsi_request?

In short, is this patch needed?

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
@@ -343,6 +343,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 +1073,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;
}

@@ -1205,6 +1203,7 @@ static int scsi_prep_fn(struct request_q
goto defer;
} else
cmd = req->special;
+ cmd->sc_request = NULL;

/* pull a tag out of the request if we have one */
cmd->tag = req->tag;
@@ -1250,7 +1249,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;
@@ -1514,7 +1513,6 @@ static void scsi_request_fn(struct reque
* cases (host limits or settings) should run the queue at some
* later time.
*/
- scsi_unprep_request(req);
spin_lock_irq(q->queue_lock);
blk_requeue_request(q, req);
sdev->device_busy--;