Commit 133d35e0 authored by Alan Stern's avatar Alan Stern Committed by James Bottomley

[PATCH] PATCH: (as70b) Update request_bufflen to match this_count

This patch addresses a problem in both sd.c and sr.c.  When a read/write
command is initialized, the routines may reduce this_count (the number of
sectors to transfer) if it exceeds the maximum allowed value (i.e., 0xffff
for READ(10)).  However, the code does not similarly alter
scmd->request_bufflen and scmd->bufflen to match the change in the CDB
value.

scmd->request_bufflen is important for the usb-storage driver, which
requires that it be exactly equal to the number of bytes transferred.
scmd->bufflen is used in the rw_intr() routines, where it is passed to
scsi_io_completion() as the number of sectors transferred if no errors
occur.

Another small change in the patch concerns the code in sr.c that checks
whether the total of the scatter-gather area lengths matches
scmd->request_bufflen.  If they don't match, the patch bumps the kernel
log message level up to KERN_ERR, and it takes the more conservative
approach of adjusting scmd->request_bufflen only if the s-g length is
smaller than the request length.
parent 350e26aa
......@@ -308,6 +308,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[4] = (unsigned char) this_count;
SCpnt->cmnd[5] = 0;
}
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * sdp->sector_size;
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
......
......@@ -340,6 +340,20 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
return 0;
}
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk(KERN_ERR "sr: mismatch count %d, bytes %d\n",
size, SCpnt->request_bufflen);
if (SCpnt->request_bufflen > size)
SCpnt->request_bufflen = SCpnt->bufflen = size;
}
}
/*
* request doesn't start on hw block boundary, add scatter pads
*/
......@@ -361,8 +375,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[1] = 0;
block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
if (this_count > 0xffff)
if (this_count > 0xffff) {
this_count = 0xffff;
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * s_size;
}
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
......@@ -390,18 +407,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
*/
SCpnt->done = rw_intr;
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk("sr: mismatch count %d, bytes %d\n", size, SCpnt->request_bufflen);
SCpnt->request_bufflen = size;
}
}
/*
* This indicates that the command is ready from our end to be
* queued.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment