public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: SCSI development list <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH] SCSI: make use of the residue value
Date: Sat, 08 Mar 2008 18:24:17 -0600	[thread overview]
Message-ID: <1205022257.2893.29.camel@localhost.localdomain> (raw)
In-Reply-To: <Pine.LNX.4.44L0.0803081643590.31118-100000@netrider.rowland.org>

On Sat, 2008-03-08 at 17:35 -0500, Alan Stern wrote:
> On Sat, 8 Mar 2008, James Bottomley wrote:
> 
> > > > The bottom line is that this patch won't work with variable length
> > > > commands like inquiry that always return a residue.
> > > 
> > > You're saying that the amount of data returned is smaller that the 
> > > amount requested because the data is variable length, right?
> > 
> > Yes.
> > 
> > > Under these circumstances the block layer should not resubmit anything.
> > > That is, it should be smart enough to know that the "missing" data does
> > > not in fact exist, as opposed to not being returned because of a
> > > retryable device error.
> > > 
> > > Aren't requests for things like VPD distinguished from regular 
> > > data-block accesses by a flag in the request structure already?  The 
> > > block layer should take this flag into account when deciding whether to 
> > > continue trying to transfer the "missing" data.  Maybe that needs to be 
> > > fixed first.
> > 
> > I'm sure Jens will look at patches.
> 
> Actually it looks as though the faulty logic is in scsi_end_request()  
> and/or scsi_io_completion().  The interface between those two routines
> is quite confusing in regard to how the "requeue" argument is used.
> 
> At the site of the first call to scsi_end_request(), the code says:
> 
> 	/* A number of bytes were successfully read.  If there
> 	 * are leftovers and there is some kind of error
> 	 * (result != 0), retry the rest.
> 	 */
> 	if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
> 		return;
> 
> 	/* good_bytes = 0, or (inclusive) there were leftovers and
> 	 * result = 0, so scsi_end_request couldn't retry.
> 	 */
> 
> These comments do a wonderful job of misdirecting the reader and 
> encouraging him to conflate "requeue" with "retry".
> 
> If there are leftovers but error is 0, it seems reasonable to requeue
> the remainder only when blk_fs_request(req) is true.  Anything else 
> could simply be a short, variable-length response.
> 
> Do you think adding something like this is the right way to go?  I'm 
> not sure it will work correctly.  What does one pass to 
> blk_end_request() to indicate that the remaining data can't be 
> transferred because it doesn't exist?
> 
> Or do you think that when blk_fs_request(req) isn't true, then 
> scsi_io_completion() should get to decide whether or not to retry it?
> 
> 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
> @@ -667,10 +667,15 @@ static struct scsi_cmnd *scsi_end_reques
>  		if (blk_pc_request(req))
>  			leftover = req->data_len;
>  
> -		/* kill remainder if no retrys */
> -		if (error && blk_noretry_request(req))
> +		/* Kill remainder if no retrys.  For request types
> +		 * other than REQ_TYPE_FS, !error indicates a normal
> +		 * variable-length response so the remainder should
> +		 * not be requeued.
> +		 */
> +		if ((error && blk_noretry_request(req)) ||
> +		    (!error && !blk_fs_request(req))) {
>  			blk_end_request(req, error, leftover);
> -		else {
> +		} else {
>  			if (requeue) {
>  				/*
>  				 * Bleah.  Leftovers again.  Stick the
> @@ -888,15 +893,16 @@ void scsi_io_completion(struct scsi_cmnd
>  	if (clear_errors)
>  		req->errors = 0;
>  
> -	/* A number of bytes were successfully read.  If there
> -	 * are leftovers and there is some kind of error
> -	 * (result != 0), retry the rest.
> +	/* A number of bytes were successfully read.  If there are
> +	 * leftovers and no error (result == 0), simply requeue them.
> +	 * But if this isn't possible, we must figure out whether to
> +	 * retry the command.
>  	 */
>  	if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL)
>  		return;
>  
>  	/* good_bytes = 0, or (inclusive) there were leftovers and
> -	 * result = 0, so scsi_end_request couldn't retry.
> +	 * result != 0, so scsi_end_request couldn't requeue.
>  	 */
>  	if (sense_valid && !sense_deferred) {
>  		switch (sshdr.sense_key) {

This is really pretty complex, and it's adjusting an already complex
path we've had quite a bit of difficulty with previously.

What I was actually looking for was something simpler.  How about this?
I'll still have to run it through the test wringer since it might still
end up causing problems if drivers are careless about their residue
calculations.

James

---

diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index e5c6f6a..96dbc63 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -759,9 +759,16 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 
 	good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len;
         if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+		int old_good_bytes = good_bytes;
 		drv = scsi_cmd_to_driver(cmd);
 		if (drv->done)
 			good_bytes = drv->done(cmd);
+		/*
+		 * USB may not give sense identifying bad sector and
+		 * simply return a residue instead.
+		 */
+		if (good_bytes == old_good_bytes)
+			good_bytes -= scsi_get_resid(cmd);
 	}
 	scsi_io_completion(cmd, good_bytes);
 }



  reply	other threads:[~2008-03-09  0:24 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-27 20:25 [PATCH] SCSI: make use of the residue value Alan Stern
2008-03-08  0:17 ` James Bottomley
2008-03-08 16:22   ` Alan Stern
2008-03-08 17:20     ` James Bottomley
2008-03-08 22:35       ` Alan Stern
2008-03-09  0:24         ` James Bottomley [this message]
2008-03-09  3:05           ` Alan Stern
2008-03-09 14:44             ` James Bottomley
2008-03-09 19:13               ` Alan Stern
2008-03-09 19:34                 ` James Bottomley
2008-03-09 21:50                   ` Alan Stern
2008-03-10 13:42                     ` Boaz Harrosh
2008-03-10 14:11                       ` Alan Stern
2008-03-10 14:31                         ` Boaz Harrosh
2008-03-10 14:50                           ` Alan Stern
2008-05-23 21:00           ` Alan Stern
  -- strict thread matches above, loose matches on Subject: below --
2008-02-20 21:26 Alan Stern

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1205022257.2893.29.camel@localhost.localdomain \
    --to=james.bottomley@hansenpartnership.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox