linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 07/30] Incorrect SCSI transfer length computation from odd sized scsi_execute_async() transfers.
@ 2007-08-10 21:50 akpm
  2007-08-13 15:10 ` Jeremy Linton
  0 siblings, 1 reply; 3+ messages in thread
From: akpm @ 2007-08-10 21:50 UTC (permalink / raw)
  To: James.Bottomley; +Cc: linux-scsi, akpm, jli

From: Jeremy Linton <jli@greshamstorage.com>

Any function which use scsi_execute_async() and transfers "odd" sized data
that doesn't align correctly with the segment sizes may have its transfer
length padded out to the closest segment size.

For writes, this results in unnecessary data being transfered to the SCSI
target.  For reads, it affects the residual data length being returned to
the application since the residual length will be based on the padded
transfer size rather than the actual request size.

The easiest way to see this is by trying to read using the SG_IO ioctl a
large (>32k) buffer size from a tape device that only has a few bytes of
data stored for the current block.  The resulting resid will generally be
incorrect.

I've fixed this simply by changing scsi_req_map_sg() so that it places the
requested transfer length in rq->data_len rather than the sum of all the sg
segments.

Signed-off-by: Jeremy Linton <jli@greshamstorage.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 drivers/scsi/scsi_lib.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

diff -puN drivers/scsi/scsi_lib.c~incorrect-scsi-transfer-length-computation-from-odd drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c~incorrect-scsi-transfer-length-computation-from-odd
+++ a/drivers/scsi/scsi_lib.c
@@ -355,7 +355,7 @@ static int scsi_req_map_sg(struct reques
 	}
 
 	rq->buffer = rq->data = NULL;
-	rq->data_len = data_len;
+	rq->data_len = bufflen;
 	return 0;
 
 free_bios:
_

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

* Re: [patch 07/30] Incorrect SCSI transfer length computation from odd sized scsi_execute_async() transfers.
  2007-08-10 21:50 [patch 07/30] Incorrect SCSI transfer length computation from odd sized scsi_execute_async() transfers akpm
@ 2007-08-13 15:10 ` Jeremy Linton
  2007-08-13 18:00   ` Mike Christie
  0 siblings, 1 reply; 3+ messages in thread
From: Jeremy Linton @ 2007-08-13 15:10 UTC (permalink / raw)
  To: akpm; +Cc: James.Bottomley, linux-scsi, Mike Christie

akpm@linux-foundation.org wrote:
> From: Jeremy Linton <jli@greshamstorage.com>
> 
> Any function which use scsi_execute_async() and transfers "odd" sized data
> that doesn't align correctly with the segment sizes may have its transfer
> length padded out to the closest segment size.
	I would like to strongly suggest that Mike Christie's patch be used instead.
http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg06032.html


I finally hit the case he was talking about (the block layer retries 0 length commands caused by a size mismatch) and 
its ugly. I'm not really sure why my initial tests weren't hitting that case, I was trying to understand why some blocks 
were getting an extra command generated while others weren't.  Sufficient to say, his patch fixes both problems, the 
incorrect transfer lengths and the extra 0 length transfer being generated.




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

* Re: [patch 07/30] Incorrect SCSI transfer length computation from odd sized scsi_execute_async() transfers.
  2007-08-13 15:10 ` Jeremy Linton
@ 2007-08-13 18:00   ` Mike Christie
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Christie @ 2007-08-13 18:00 UTC (permalink / raw)
  To: Jeremy Linton; +Cc: akpm, James.Bottomley, linux-scsi

[-- Attachment #1: Type: text/plain, Size: 1070 bytes --]

Jeremy Linton wrote:
> akpm@linux-foundation.org wrote:
>> From: Jeremy Linton <jli@greshamstorage.com>
>>
>> Any function which use scsi_execute_async() and transfers "odd" sized 
>> data
>> that doesn't align correctly with the segment sizes may have its transfer
>> length padded out to the closest segment size.
>     I would like to strongly suggest that Mike Christie's patch be used 
> instead.
> http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg06032.html
> 
> 
> I finally hit the case he was talking about (the block layer retries 0 
> length commands caused by a size mismatch) and its ugly. I'm not really 
> sure why my initial tests weren't hitting that case, I was trying to 
> understand why some blocks were getting an extra command generated while 
> others weren't.  Sufficient to say, his patch fixes both problems, the 
> incorrect transfer lengths and the extra 0 length transfer being generated.
> 

I am having trouble inlining the patch properly with my mailer. Here is 
the patch from that thread attached if James or Andrew needs it.

[-- Attachment #2: usebufflen.patch --]
[-- Type: text/x-patch, Size: 1465 bytes --]

sg's may have setup a the buffer with a different length than
the transfer length so we should be using the bufflen passed
in as the request's data len.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>


diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5f95570..30ae831 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -301,7 +301,7 @@ static int scsi_req_map_sg(struct reques
 {
 	struct request_queue *q = rq->q;
 	int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	unsigned int data_len = 0, len, bytes, off;
+	unsigned int data_len = bufflen, len, bytes, off;
 	struct page *page;
 	struct bio *bio = NULL;
 	int i, err, nr_vecs = 0;
@@ -310,10 +310,15 @@ static int scsi_req_map_sg(struct reques
 		page = sgl[i].page;
 		off = sgl[i].offset;
 		len = sgl[i].length;
-		data_len += len;
 
-		while (len > 0) {
+		while (len > 0 && data_len > 0) {
+			/*
+			 * sg sends a scatterlist that is larger than
+			 * the data_len it wants transferred for certain
+			 * IO sizes
+			 */
 			bytes = min_t(unsigned int, len, PAGE_SIZE - off);
+			bytes = min(bytes, data_len);
 
 			if (!bio) {
 				nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
@@ -345,12 +350,13 @@ static int scsi_req_map_sg(struct reques
 
 			page++;
 			len -= bytes;
+			data_len -=bytes;
 			off = 0;
 		}
 	}
 
 	rq->buffer = rq->data = NULL;
-	rq->data_len = data_len;
+	rq->data_len = bufflen;
 	return 0;
 
 free_bios:

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

end of thread, other threads:[~2007-08-13 18:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-10 21:50 [patch 07/30] Incorrect SCSI transfer length computation from odd sized scsi_execute_async() transfers akpm
2007-08-13 15:10 ` Jeremy Linton
2007-08-13 18:00   ` Mike Christie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).