          <<< SSAG::DISK$ARCH2:[NOTES$LIBRARY.SSAG]ASK_SSAG.NOTE;7 >>>
                    -< Ask the Storage Architecture Group >-
================================================================================
Note 6113.2            RMS errors on Raid 200 controller!                 2 of 2
EPS::VANDENHEUVEL "Hein"                            107 lines  30-OCT-1996 15:13
         -< program to clear relative files with multiple large QIOs >-
--------------------------------------------------------------------------------
    
    Hmmm, 
    	I just got a chance to try on an KZESC and it worked just fine.
    	What Drives where hooked up? Perhaps the drives failed to erase?
    
    	At any rate, they can always create their relative files in a
    	place where that appears to work and then copy to the stripeset
    	for the production work.
    
    	Alternativly, they could create the file on the stripeset and
    	upon failure use the include program (I felt like throwing some
    	code this afternoon :-) to scrub the bits. This workaround should
    	prove a whole lost faster than the first.
    
    Hein.
    
/* relative_file_erase.c    Hein van den Heuvel, Oct 1996 */
#include stdio
#include iodef
#include ssdef
#include rms
#define MYBUFSIZ 64
#define MAXIO 64
#define NUMIO 4
int	sys$dclast(), sys$open(), sys$qio(), strlen();
void	lib$init_timer(), lib$show_timer(), sys$setast(), sys$hiber(), sys$wake();
int	last_block, channel, vbn=2, bufsiz=MYBUFSIZ;
volatile int	numio=NUMIO;
typedef struct { int vbn; char *buf; short iosb[4]; } io_control;

void io_ast( io_control *io )
{
    int i, io_size, status;
    if (!(io->iosb[0] & 1)) {
	printf ("IO error %d, current vbn %d, writing vbn %d\n", 
		io->iosb[0], vbn, io->vbn);
	vbn = last_block;
	}

    io_size = last_block - vbn;
    if (io_size > 0 ) {
        if (io_size > bufsiz) io_size = bufsiz;
	io->vbn = vbn;	/* this IO */
	status = sys$qio(0, channel, IO$_WRITEVBLK, &io->iosb[0], &io_ast, 
			 io, io->buf, io_size*512, vbn, 0, 0, 0);
	if (status & 1) {
	    vbn += io_size; /* next IO */
	    } else {
	    if (numio==0 || status != SS$_EXQUOTA) {
		printf ("Failure to issue QIO. Error %d, vbn %d\n", 
		    status, vbn);
		sys$wake(0,0);
		}
	    if (status == SS$_EXQUOTA) numio--;    /* walk away from this IO */
	    }
	} else numio--;
    
    if (numio == 0) sys$wake(0,0);
}

main (int argc, char *argv[])
    {
    io_control io[MAXIO];
    int	i, status;
    char *buf, *calloc();
    struct FAB fab;

    lib$init_timer();
    if (argc < 2) { printf (
    "Usage: $erase <filename> <vbn(%d)> <concurrent_io(%d)> <blocks_per_io(%d)>\n",
	    vbn, numio, bufsiz);
	return 16;
	}
    if (argc > 2) sscanf(argv[2], "%d", &vbn);
    if (argc > 3) sscanf(argv[3], "%d", &numio);
    if (argc > 4) sscanf(argv[4], "%d", &bufsiz);
    if (numio > MAXIO) numio = MAXIO;
    fab = cc$rms_fab;
    fab.fab$l_fna = argv[1];
    fab.fab$b_fns = strlen( argv[1] );
    fab.fab$b_fac = FAB$M_GET | FAB$M_PUT;
    fab.fab$l_fop = FAB$M_UFO;
    status=sys$open(&fab);
    if (!(status&1)) return status;
    /* if (fab.fab$b_org!=FAB$C_REL) return RMS$_ORG; */
    last_block = fab.fab$l_alq;
    channel = fab.fab$l_stv;
    buf = calloc(bufsiz*512);
    sys$setast(0);
    for (i=0; i<numio; i++) {
	io[i].vbn=0;
	io[i].buf=buf;
	io[i].iosb[0]=1;
	status = sys$dclast ( &io_ast, &io[i], 0);
	if (status == SS$_EXQUOTA) { 
	    numio = i;
	    status = 1;
	    }
	if (!(status&1)) return status;
	}
    sys$setast(1);
    sys$hiber(0);
    lib$show_timer();
    return;
}
    
    	
