Subject: Re: disk verification/stress test?
To: Timm Wetzel <twetzel@gwdg.de>
From: Darrin B. Jewell <jewell@mit.edu>
List: port-next68k
Date: 07/22/1999 04:50:35
Timm Wetzel <twetzel@gwdg.de> writes:
> Can anybody recommend some tools to verify/stress test a hard disk,
> preferably with NS3.3?
Well, I wrote a quick hack to stress test my next68k esp driver, and
have included it below. (The esp driver doesn't pass it yet)
I have been using it on the raw scsi device as follows:
# ./testio write 1234 2048000 /dev/rsd0d
# ./testio read 1234 2048000 /dev/rsd0d
Where "1234" is a random number seed which determines the repeatable
test io pattern to be performed and "2048000" is the size of the media
in 512 byte blocks.
This program will pick:
. a random number of blocks to transfer
. a random number of blocks to transfer per read/write
. a random number of blocks to offset the transfer
. a random byte alignment to use for reads/writes
And will then will open the file, seek to the offset and then write a
pseudo random test pattern or read and compare the results with the
expected pattern.
Darrin
/* testio.c */
/*
* Copyright (c) 1999 Darrin B. Jewell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Darrin B. Jewell
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
/* Size of a block: */
#define BLKSIZE 512
/* Maximum number of blocks allowed in a single io operation: */
#define MAXBLKS (1<<11) /* 2048 */
int
main(int argc, char *argv[])
{
int fd;
int r;
unsigned char *buf;
unsigned char *iobuf;
int total = 0;
unsigned long seed;
unsigned long blkcnt;
const char *filename;
unsigned long ioblen;
unsigned long ioalgn;
unsigned long iosize;
unsigned long iooffs;
int writeflag;
if (argc != 5) {
fprintf(stderr,"usage: %s read|write seed blkcnt filename\n",argv[0]);
return(EXIT_FAILURE);
}
writeflag = !strcmp(argv[1],"write");
seed = strtoul(argv[2],NULL,10);
blkcnt = strtoul(argv[3],NULL,10);
filename = argv[4];
srandom(seed);
iosize = (random()%blkcnt)+1; /* size of the region read/written, in blocks */
iooffs = random()%(blkcnt-iosize+1); /* offset of the region read/written, in blocks */
ioblen = (random()%(MAXBLKS>iosize?iosize:MAXBLKS))+1; /* number of blocks per read/write */
ioalgn = (random()%BLKSIZE); /* alignment of data in a block */
/* reserve the first 100 values for this seed */
{
int i;
for(i=4;i<100;i++) {
random();
}
}
fprintf(stdout,
"seed = %lu (0x%x)\tSpecified random number seed.\n"
"blkcnt = %lu (0x%x)\tSpecified number of blocks available on media.\n"
"ioblen = %lu (0x%x)\tBlocks per read or write operation.\n"
"ioalgn = %lu (0x%x)\tByte alignment of data in a read or write operation.\n"
"iosize = %lu (0x%x)\tBlocks to be read or written.\n"
"iooffs = %lu (0x%x)\tBlocks offset from beginning of media.\n",
seed,seed,
blkcnt,blkcnt,
ioblen,ioblen,
ioalgn,ioalgn,
iosize,iosize,
iooffs,iooffs);
fflush(stdout);
{
assert(ioalgn < ioblen*BLKSIZE);
buf = malloc(ioblen*BLKSIZE+ioalgn);
assert(buf);
iobuf = buf+ioalgn-((unsigned long)buf%ioalgn);
}
fd = open(filename,O_RDWR|O_SYNC|O_RSYNC|O_DSYNC|O_CREAT, 0x777);
if (fd == -1) {
perror("open");
return(EXIT_FAILURE);
}
fprintf(stdout,"open successful\n");
{
off_t or;
or = lseek(fd,iooffs*BLKSIZE,SEEK_SET);
if (or == -1) {
perror("lseek");
return(EXIT_FAILURE);
}
assert(or == iooffs*BLKSIZE);
}
fprintf(stdout,"lseek successful\n");
{
long i;
for(i=0;i<(ioblen*BLKSIZE);i++) {
iobuf[i] = 0xff;
}
}
fprintf(stdout,"pages initialized\n");
{
double fraction = 0.0;
do {
if (writeflag) {
long i;
/* Seed the buffer with random values */
for(i=0;i<(ioblen*BLKSIZE);i++) {
iobuf[i] = random()%(UCHAR_MAX+1);
}
r = write(fd,iobuf,ioblen*BLKSIZE);
if (r == -1) {
perror("write");
break;
}
} else {
long i;
/* Initialize buffer to 0 */
for(i=0;i<(ioblen*BLKSIZE);i++) {
iobuf[i] = 0;
}
r = read(fd,iobuf,ioblen*BLKSIZE);
if (r == -1) {
perror("read");
break;
}
if (r != ioblen*BLKSIZE) {
fprintf(stderr,"short read, got %d, expecting %d\n",r,ioblen*BLKSIZE);
break;
}
/* compare the buffer with expected values */
for(i=0;i<(ioblen*BLKSIZE);i++) {
int rval;
rval = random()%(UCHAR_MAX+1);
if (iobuf[i] != rval) {
fprintf(stderr,"Data mismatched at byte %d (0x%08x) got %d (0x%02x) expecting %d (0x%02x)\n",
total+i,total+i,iobuf[i],iobuf[i],rval,rval);
break;
}
}
if (i!=(ioblen*BLKSIZE)) break;
}
assert(r >= 0);
total += r;
if (r != ioblen*BLKSIZE) {
fprintf(stdout,"\n%s returned %d, total %d (0x%08x)\n",
writeflag?"write":"read",r,total,total);
break;
}
#if 1
else {
fprintf(stdout,".");
fflush(stdout);
}
#endif
#if 0
{
double frac = (total / (iosize *BLKSIZE));
if (frac > (fraction+0.01)) {
fprintf(stdout,"wrote %lu of %lu transfers, %f %%\n",
total/(ioblen*BLKSIZE),
iosize/ioblen,
frac);
fraction = frac;
}
}
#endif
} while(r && (total < (iosize*BLKSIZE)));
}
r = close(fd);
if (r == -1) {
perror("close");
return(EXIT_FAILURE);
}
fprintf(stdout,"close successful\n");
free(buf);
return(EXIT_SUCCESS);
}