From: drew@hazelrah.cs.colorado.edu (Drew Eckhardt)
Subject: Seagate scatter / gather patches
Organization: University of Colorado at Boulder
Date: Thu, 28 Jan 1993 00:01:42 GMT

Ok, here's the first installment of the Seagate patches,   This one 
implements scatter-gather (I saw a 4X speed improvement).  As far 
as CPU usage and "hanging" - things should improve if your filesystems
aren't too fragmented.

Note that the current Seagate routines will not transfer >
~500-600K/sec. If your disk is faster than this, you'll have to 
format at something greater than a 1:1 interleave if you want to 
see the same four-fold performance increase.

I have another patch on the way that will allow the use of the 
Seagate's hardware handshaking, it will be posted "RSN" (the 
definition of RSN being somewhere between a few hours and six months).
It should rectify the maximum transfer rate restriction.

Here are some figures for your perusal : 


IOZONE results (using recommended file sizes, minix filesystems).
To reduce buffer cache size (and therefore required filesize under 
IOZONE), I loaded the memory by running X11R5 + 3 xterms + xman + xload + 
xsysinfo + twm.

System : i386-33, 8M main memory, 64K cache
SCSI host : Seagate ST02
Software : Linux .99.3 
Disk : /dev/sda3 Seagate 296N, 3:1 interleave

Writing the 3 Megabyte file, 'iozone.tmp'...50.610000 seconds
Reading the file...62.110000 seconds

IOZONE performance measurements:
        62156 bytes/second for writing the file
        50647 bytes/second for reading the file

Software : Linux .99.4 + Seagate Scatter / Gather patches
Disk : /dev/sda3 Seagate 296N, 3:1 interleave

Writing the 3 Megabyte file, 'iozone.tmp'...12.840000 seconds
Reading the file...16.120000 seconds

IOZONE performance measurements:
        244994 bytes/second for writing the file
        195144 bytes/second for reading the file

And, as a baseline : 

Software : Linux .99.4 + Seagate Scatter / Gather patches
Disk : /dev/hda2 Seagate 1144A 1:1 interleave

Writing the 3 Megabyte file, 'iozone.tmp'...7.500000 seconds
Reading the file...15.520000 seconds

IOZONE performance measurements:
        419430 bytes/second for writing the file
        202688 bytes/second for reading the file

Software : Linux .99.3 

The patch : 


*** 1.1	1993/01/27 20:33:13
--- linux/kernel/blk_drv/scsi/seagate.c	1993/01/27 22:16:53
***************
*** 225,230 ****
--- 225,233 ----
  
  static unsigned char current_target, current_lun;
  static unsigned char *current_cmnd, *current_data;
+ static int current_nobuffs;
+ static struct scatterlist *current_buffer;
+ 
  static int current_bufflen;
  static void (*done_fn)(Scsi_Cmnd *) = NULL;
  static Scsi_Cmnd * SCint = NULL;
***************
*** 353,358 ****
--- 356,363 ----
  	{
  	int len;			
  	unsigned char *data;	
+ 	struct scatterlist *buffer;
+ 	int nobuffs;
  	int clock;			
  	int temp;
  	Scsi_Cmnd * SCtmp;
***************
*** 371,379 ****
  	unsigned char message = 0;
  	register unsigned char status_read;
  
- 	len=bufflen;
- 	data=(unsigned char *) buff;
- 
  	incommand = 0;
  	st0x_aborted = 0;
  
--- 376,381 ----
***************
*** 455,463 ****
  				hostno, temp);
  			return (DID_BAD_INTR << 16);
  			}
!                 data=current_data;      /* WDE add */
                  cmnd=current_cmnd;      /* WDE add */
                  len=current_bufflen;    /* WDE add */
  
  /*
   * 	We have determined that we have been selected.  At this point, 
--- 457,468 ----
  				hostno, temp);
  			return (DID_BAD_INTR << 16);
  			}
! 
! 		buffer=current_buffer;	
                  cmnd=current_cmnd;      /* WDE add */
+                 data=current_data;      /* WDE add */
                  len=current_bufflen;    /* WDE add */
+ 		nobuffs=current_nobuffs;
  
  /*
   * 	We have determined that we have been selected.  At this point, 
***************
*** 606,611 ****
--- 611,629 ----
  				}
  			return retcode(st0x_aborted);
  			}	
+ 
+ /* Establish current pointers.  Take into account scatter / gather */
+ 
+         if ((nobuffs = SCint->use_sg)) {
+                 buffer = (struct scatterlist *) SCint->buffer;
+                 len = buffer->length;
+                 data = (unsigned char *) buffer->address;
+         } else {
+                 buffer = NULL;
+                 len = SCint->bufflen;
+                 data = (unsigned char *) SCint->buffer;
+         }
+ 
  		}
  
  	CONTROL = BASE_CMD | CMD_DRVR_ENABLE | 
***************
*** 748,753 ****
--- 766,779 ----
  /* clobbered */
  "ebx", "ecx", "edi", "esi"); 
  
+                         if (!len && nobuffs) {
+                                 --nobuffs;
+                                 ++buffer;
+                                 len = buffer->length;
+                                 data = (unsigned char *) buffer->address;
+                         }
+ 
+ 
  			break;
  
  		case REQ_DATAIN : 
***************
*** 811,816 ****
--- 837,850 ----
  "0" (data), "1" (len) :
  /* clobbered */
  "ebx", "ecx", "edi", "esi"); 
+ 
+                         if (!len && nobuffs) {
+                                 --nobuffs;
+                                 ++buffer;
+                                 len = buffer->length;
+                                 data = (unsigned char *) buffer->address;
+                         }
+ 
  			break;
  
  		case REQ_CMDOUT : 
***************
*** 858,864 ****
--- 892,901 ----
  			case DISCONNECT :
  				should_reconnect = 1;
                                  current_data = data;    /* WDE add */
+ 				current_buffer = buffer;
                                  current_bufflen = len;  /* WDE add */
+ 				current_nobuffs = nobuffs;
+ 
  #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
  				printk("scsi%d : disconnected.\n", hostno);
  				done=1;
***************
*** 877,891 ****
  				done=1;
  				break;
  			case SAVE_POINTERS :
! 				current_data = data;	/* WDE mod */
                                  current_bufflen = len;  /* WDE add */
  #if (DEBUG & PHASE_MSGIN)
  				printk("scsi%d : pointers saved.\n", hostno);
  #endif 
  				break;
  			case RESTORE_POINTERS:
! 				data=current_data;	/* WDE mod */
  				cmnd=current_cmnd;
  #if (DEBUG & PHASE_MSGIN)
  				printk("scsi%d : pointers restored.\n", hostno);
  #endif
--- 914,933 ----
  				done=1;
  				break;
  			case SAVE_POINTERS :
! 				current_buffer = buffer;
                                  current_bufflen = len;  /* WDE add */
+ 				current_data = data;	/* WDE mod */
+ 				current_nobuffs = nobuffs;
  #if (DEBUG & PHASE_MSGIN)
  				printk("scsi%d : pointers saved.\n", hostno);
  #endif 
  				break;
  			case RESTORE_POINTERS:
! 				buffer=current_buffer;
  				cmnd=current_cmnd;
+ 				data=current_data;	/* WDE mod */
+ 				len=current_bufflen;
+ 				nobuffs=current_nobuffs;
  #if (DEBUG & PHASE_MSGIN)
  				printk("scsi%d : pointers restored.\n", hostno);
  #endif
-- 
Boycott AT&T for their absurd anti-BSDI lawsuit. | Drew Eckhardt
Condemn Colorado for Amendment Two.		 | drew@cs.colorado.edu
Use Linux, the fast, flexible, and free 386 unix |  
Newsgroups: comp.os.linux