diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2007-03-13 13:52:29 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:38:17 -0400 |
commit | bd441deaf341c524b28fd72831ebf6fef88f1c41 (patch) | |
tree | f75f1170a90b55992a340c64e2ed52ecbfb19bce /drivers/scsi/scsi_lib.c | |
parent | 358147403d1506ee43335c152fa3864d90f5ef6e (diff) |
[SCSI] fix write buffer length in scsi_req_map_sg()
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>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a417a6ff9f9..277f1b64e9a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -301,7 +301,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, | |||
301 | { | 301 | { |
302 | struct request_queue *q = rq->q; | 302 | struct request_queue *q = rq->q; |
303 | int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | 303 | int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; |
304 | unsigned int data_len = 0, len, bytes, off; | 304 | unsigned int data_len = bufflen, len, bytes, off; |
305 | struct page *page; | 305 | struct page *page; |
306 | struct bio *bio = NULL; | 306 | struct bio *bio = NULL; |
307 | int i, err, nr_vecs = 0; | 307 | int i, err, nr_vecs = 0; |
@@ -310,10 +310,15 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, | |||
310 | page = sgl[i].page; | 310 | page = sgl[i].page; |
311 | off = sgl[i].offset; | 311 | off = sgl[i].offset; |
312 | len = sgl[i].length; | 312 | len = sgl[i].length; |
313 | data_len += len; | ||
314 | 313 | ||
315 | while (len > 0) { | 314 | while (len > 0 && data_len > 0) { |
315 | /* | ||
316 | * sg sends a scatterlist that is larger than | ||
317 | * the data_len it wants transferred for certain | ||
318 | * IO sizes | ||
319 | */ | ||
316 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); | 320 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); |
321 | bytes = min(bytes, data_len); | ||
317 | 322 | ||
318 | if (!bio) { | 323 | if (!bio) { |
319 | nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); | 324 | nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages); |
@@ -345,12 +350,13 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, | |||
345 | 350 | ||
346 | page++; | 351 | page++; |
347 | len -= bytes; | 352 | len -= bytes; |
353 | data_len -=bytes; | ||
348 | off = 0; | 354 | off = 0; |
349 | } | 355 | } |
350 | } | 356 | } |
351 | 357 | ||
352 | rq->buffer = rq->data = NULL; | 358 | rq->buffer = rq->data = NULL; |
353 | rq->data_len = data_len; | 359 | rq->data_len = bufflen; |
354 | return 0; | 360 | return 0; |
355 | 361 | ||
356 | free_bios: | 362 | free_bios: |