From: Drew Eckhardt (drew@hazelrah.cs.colorado.edu)
Date: 01/27/93


From: drew@hazelrah.cs.colorado.edu (Drew Eckhardt)
Subject: Seagate scatter / gather patches
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 |