aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/st.c
diff options
context:
space:
mode:
authorKai Makisara <Kai.Makisara@kolumbus.fi>2005-11-13 03:04:44 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-15 18:17:03 -0500
commit787926b1b2d21d42ca462dc736b77f1a4a30c503 (patch)
tree97d5e0dc96f7ccac43052706da15f5346c4b8082 /drivers/scsi/st.c
parentdefd94b75409b983f94548ea2f52ff5787ddb848 (diff)
[SCSI] Fix st oops with new scsi_execute infrastructure
Patch from Kai minus last sg_segs clearing which was merged already. > > Was there a oops or lockup or any debug output you can send me? I will try > > some more large request tests with scsi_debug. You also have to compile your > > kernel with SCSI_MAX_PHYS_SEGMENTS == 255 to get larger requests now. > It was an oops in sgl_unmap_user_pages(). The reason is this: /* XXX: just for debug. Remove when PageReserved is removed */ BUG_ON(PageReserved(page)); I was using /dev/zero as input and it triggers this. When I used a file as input, this did not trigger. Should this BUG_ON be removed? In the same log I noticed that there was another ->sg_segs inconsistency. Also, the field ->last_SRpnt was not reset when scsi_execute_async() failed. This caused the error message "Async command already active" later and prevented proper close. While doing the changes, I noticed that the current code (since 2.6.0-test4) does not set the pages dirty when reading with direct i/o. All of these st problems (including the one I sent earlier) are fixed in the patch at the end of this message. These fixes should probably be included already in 2.6.15. After these fixes, the tape seems to operate as expected. Without other changes, the largest block size with sym53c896 SCSI adapter is 384 kB. The maximum number of sg segments is set to 96 and clustering is disabled in the driver. 96 x 4 kB = 384 kB. OK. I enabled clustering and set max_sectors to 10000 in the SCSI HBA driver. Now the block size limit is 5000 kB as expected. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/st.c')
-rw-r--r--drivers/scsi/st.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 26e13dc7bcdb..2096d137f5ee 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -511,9 +511,11 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
511 511
512 if (scsi_execute_async(STp->device, cmd, direction, 512 if (scsi_execute_async(STp->device, cmd, direction,
513 &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs, 513 &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
514 timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) 514 timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
515 /* could not allocate the buffer or request was too large */ 515 /* could not allocate the buffer or request was too large */
516 (STp->buffer)->syscall_result = (-EBUSY); 516 (STp->buffer)->syscall_result = (-EBUSY);
517 (STp->buffer)->last_SRpnt = NULL;
518 }
517 else if (do_wait) { 519 else if (do_wait) {
518 wait_for_completion(waiting); 520 wait_for_completion(waiting);
519 SRpnt->waiting = NULL; 521 SRpnt->waiting = NULL;
@@ -1449,14 +1451,15 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
1449 1451
1450 1452
1451/* Can be called more than once after each setup_buffer() */ 1453/* Can be called more than once after each setup_buffer() */
1452static void release_buffering(struct scsi_tape *STp) 1454static void release_buffering(struct scsi_tape *STp, int is_read)
1453{ 1455{
1454 struct st_buffer *STbp; 1456 struct st_buffer *STbp;
1455 1457
1456 STbp = STp->buffer; 1458 STbp = STp->buffer;
1457 if (STbp->do_dio) { 1459 if (STbp->do_dio) {
1458 sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, 0); 1460 sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
1459 STbp->do_dio = 0; 1461 STbp->do_dio = 0;
1462 STbp->sg_segs = 0;
1460 } 1463 }
1461} 1464}
1462 1465
@@ -1729,7 +1732,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
1729 out: 1732 out:
1730 if (SRpnt != NULL) 1733 if (SRpnt != NULL)
1731 st_release_request(SRpnt); 1734 st_release_request(SRpnt);
1732 release_buffering(STp); 1735 release_buffering(STp, 0);
1733 up(&STp->lock); 1736 up(&STp->lock);
1734 1737
1735 return retval; 1738 return retval;
@@ -1787,7 +1790,7 @@ static long read_tape(struct scsi_tape *STp, long count,
1787 SRpnt = *aSRpnt; 1790 SRpnt = *aSRpnt;
1788 SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE, 1791 SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
1789 STp->device->timeout, MAX_RETRIES, 1); 1792 STp->device->timeout, MAX_RETRIES, 1);
1790 release_buffering(STp); 1793 release_buffering(STp, 1);
1791 *aSRpnt = SRpnt; 1794 *aSRpnt = SRpnt;
1792 if (!SRpnt) 1795 if (!SRpnt)
1793 return STbp->syscall_result; 1796 return STbp->syscall_result;
@@ -2058,7 +2061,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
2058 SRpnt = NULL; 2061 SRpnt = NULL;
2059 } 2062 }
2060 if (do_dio) { 2063 if (do_dio) {
2061 release_buffering(STp); 2064 release_buffering(STp, 1);
2062 STbp->buffer_bytes = 0; 2065 STbp->buffer_bytes = 0;
2063 } 2066 }
2064 up(&STp->lock); 2067 up(&STp->lock);