home *** CD-ROM | disk | FTP | other *** search
- /*
- * File system test suite.
- *
- * Simson L. Garfinkel
- *
- */
-
- /* There are five basic tests:
- *
- * Test #1: Image store.
- * This test examines the raw read/write performance of the
- * filesystem.
- * 1 Write, 10 Reads of a 256K file (512x512), delete file
- * Repeat 100 times.
- *
- * Test #2: Same as test #1, but with smaller files.
- *
- * Test #3: Database application. Write a 2MB file, and a 100K file.
- * Randomly read/write 600 byte entries in the first and 20 byte
- * entries in the second
- *
- * Test #4: Directory write/read, testing directory caching. Create
- * 1000 subdirectories, and 10 files in each. Try to open
- * and then close each one, directory-wise.
- *
- * Test #5: Same as test #4, except do all of the file#1s in each
- * directory, all of the file#2s in each directory, ...
- *
- * Test #6: Do all tests randomly, until they are all done.
- */
-
-
- int debug=0;
-
- #define KBYTE 1024
- #define KBUFSIZE 60
- #define BUFSIZE KBUFSIZE * KBYTE
-
- char buf[BUFSIZE];
-
-
- #define MAXTESTS 6
-
- #define TEST1_WRITES 5
- #define TEST1_FILESIZE 256L * KBYTE
- #define TEST1_READS_PER_WRITE 10
- #define TEST1_FILENAME "TEST1"
-
- #define TEST2_WRITES 20
- #define TEST2_FILESIZE 30L * KBYTE
- #define TEST2_READS_PER_WRITE 10
- #define TEST2_FILENAME "TEST2"
-
- #define TEST3_REPEATS 500
- #define TEST3_FILE1NAME "TEST3.1"
- #define TEST3_FILE2NAME "TEST3.2"
- #define TEST3_FILE1SIZE 2048L * KBYTE
- #define TEST3_FILE2SIZE 256L * KBYTE
-
- int test3_xfer[2] = {600,20};
- long test3_lens[2] = {TEST3_FILE1SIZE,TEST3_FILE2SIZE};
-
- #define TEST4_DIRS 25
- #define TEST4_DIRNAME "T4-%d"
- #define TEST4_FILENAME "FILE%d"
- #define TEST4_FILES 10
-
- int TEST5_DIRS = 25;
- #define TEST5_DIRNAME "T5-%d"
- #define TEST5_FILENAME "FILE%d"
- #define TEST5_FILES 10
-
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <io.h>
-
-
- #ifndef O_BINARY /* if not on MSDOS */
- #define O_BINARY 0
- #endif
-
- int test1_action(), test2_action(), test3_action();
- int test4_action(), test5_action(), test6_action();
-
- int (*action[MAXTESTS])() = {test1_action, test2_action,
- test3_action, test4_action, test5_action,
- test6_action };
-
-
-
- /* Define our own random number generator, so it is the same across all
- * systems.
- */
-
- unsigned long rndnum = 0;
-
- long rnd_()
- {
- rndnum = (rndnum + 1234567L) % 65536;
- return(rndnum >> 5);
- }
-
- long rnd(x)
- int x;
- {
- return(rnd_() % x);
- }
-
-
- /* debuggable system calls */
- int smkdir(dir)
- char *dir;
- {
- int q;
-
- if(debug){
- printf("mkdir(%s)\n",dir);
- if(debug==1) return(0);
- }
- q = mkdir(dir,0666); /* 0666 for unix systems */
- if(q>=0) return(q);
- perror(dir);
- exit(1);
- }
-
-
- int srmdir(dir)
- char *dir;
- {
- int q;
-
- if(debug){
- printf("rmdir(%s)\n",dir);
- if(debug==1) return(0);
- }
- q = rmdir(dir);
- if(q>=0) return(q);
- perror(dir);
- exit(1);
- }
-
-
- int screat(file,mode)
- char *file;
- int mode;
- {
- int q;
-
- if(debug){
- printf("creat(%s,%o)\n",file,mode);
- if(debug==1) return(0);
- }
- q = creat(file,mode);
- if(q>=0) return(q);
- perror(file);
- exit(1);
- }
-
-
- int sopen(file,flags,mode)
- char *file;
- int flags,mode;
- {
- static sopenfd=0;
- int fd;
-
- if(debug){
- printf("open(%s,%x,%o)\n",file,flags,mode);
- if(debug==1) return(++sopenfd);
- }
- fd = open(file,flags,mode);
- if(fd>0) return(fd);
- perror(file);
- exit(1);
- }
-
- long slseek(fd,offset,whence)
- int fd,whence;
- long offset;
- {
- long q;
-
- if(debug){
- printf("lseek(%d,%ld,%d)\n",fd,offset,whence);
- if(debug==1) return(offset);
- }
- q = lseek(fd,offset,whence);
- if(q>=0) return(q);
- printf("q=%ld\n",q);
- perror("lseek");
- exit(1);
- }
-
- int swrite(fd,buf,len)
- int fd;
- char *buf;
- unsigned len;
- {
- if(debug){
- printf("write(%d,buf,%u)\n",fd,len);
- if(debug==1) return;
- }
- if(write(fd,buf,len)!=len){
- perror("write");
- exit(1);
- }
- }
-
-
- int sread(fd,buf,len)
- int fd;
- char *buf;
- unsigned len;
- {
- int q;
- if(debug){
- printf("read(%d,buf,%u)\n",fd,len);
- if(debug==1) return;
- }
- if((q=read(fd,buf,len))!=len){
- printf("q=%d len=%d\n",q,len);
- perror("read");
- exit(1);
- }
- }
-
- int sclose(fd)
- int fd;
- {
- if(debug){
- printf("close(%d)\n",fd);
- if(debug==1) return;
- }
- if(close(fd)<0){
- perror("close");
- exit(1);
- }
- }
-
-
- int sunlink(filename)
- char *filename;
- {
- if(debug){
- printf("cunlink(%s)\n",filename);
- if(debug==1) return;
- }
- if(unlink(filename)<0){
- perror(filename);
- exit(1);
- }
- }
-
-
- /* This is the action procedure for the first test. It performs the next
- * part of the test, increments the state variables, and returns. If all
- * of the tests have been finished, it returns 0, otherwise it returns 1.
- *
- * Action performed depends on the variable state, which can be:
- * 0 - open file for writing, truncating, &c.
- * 1 - write data till filled.
- * 2 - close file for writing.
- * 3 - open file for reading.
- * 4 - read data till finished.
- * 5 - close file, repeat to state 3 until number of reads is done.
- */
-
- int test1_action()
- {
- static long repeat = 0; /* times test has been repeated */
- static long bytesleft = 0; /* bytes to transfer */
- static state = 0; /* next action to do */
- static readrepeat;
- static fd;
-
- unsigned xfer;
-
- if(repeat >= TEST1_WRITES) return(0);
-
- switch(state){
- case 0: fd = sopen(TEST1_FILENAME,
- O_WRONLY | O_CREAT | O_BINARY | O_TRUNC,0666);
- state++;
- bytesleft = TEST1_FILESIZE;
- readrepeat = TEST1_READS_PER_WRITE;
- return(1);
-
- case 1: xfer = min(BUFSIZE,bytesleft);
- swrite(fd,buf,xfer);
- bytesleft -= xfer;
- if(bytesleft==0){
- state++;
- }
- return(1);
-
- case 2: sclose(fd);
- state++;
- return(1);
-
- case 3: fd = sopen(TEST1_FILENAME, O_RDONLY | O_BINARY ,0666);
- state++;
- bytesleft = TEST1_FILESIZE;
- return(1);
-
- case 4: xfer = min(BUFSIZE,bytesleft);
- sread(fd,buf,xfer);
- bytesleft -= xfer;
- if(bytesleft==0){
- state = 5;
- }
- return(1);
-
- case 5: sclose(fd);
- if(--readrepeat > 0){
- state = 3;
- return(1);
- }
- sunlink(TEST1_FILENAME);
- repeat ++;
- state = 0;
- return(1);
-
- default:
- fprintf(stderr,"test1 - unknown state %d\n",state);
- return(-1);
- }
- }
-
-
- /* This is the second test. It is identical to the first test, except
- * that it uses TEST2 variables, which are different values.
- *
- * This could be rewritten so that test1 & test2 called a common driver,
- * but I think that would introduce more complexity than is warranted
- */
-
-
-
- int test2_action()
- {
- static long repeat = 0; /* times test has been repeated */
- static long bytesleft = 0; /* bytes to transfer */
- static state = 0; /* next action to do */
- static readrepeat;
- static fd;
-
- unsigned xfer;
-
- if(repeat >= TEST2_WRITES) return(0);
-
- switch(state){
- case 0: fd = sopen(TEST2_FILENAME,
- O_WRONLY | O_CREAT | O_BINARY | O_TRUNC,0666);
- state++;
- bytesleft = TEST2_FILESIZE;
- readrepeat = TEST2_READS_PER_WRITE;
- return(1);
-
- case 1: xfer = min(BUFSIZE,bytesleft);
- swrite(fd,buf,xfer);
- bytesleft -= xfer;
- if(bytesleft==0){
- state++;
- }
- return(1);
-
- case 2: sclose(fd);
- state++;
- return(1);
-
- case 3: fd = sopen(TEST2_FILENAME, O_RDONLY | O_BINARY ,0666);
- state++;
- bytesleft = TEST2_FILESIZE;
- return(1);
-
- case 4: xfer = min(BUFSIZE,bytesleft);
- sread(fd,buf,xfer);
- bytesleft -= xfer;
- if(bytesleft==0){
- state = 5;
- }
- return(1);
-
- case 5: sclose(fd);
- if(--readrepeat > 0){
- state = 3;
- return(1);
- }
- sunlink(TEST2_FILENAME);
- repeat ++;
- state = 0;
- return(1);
-
- default:
- fprintf(stderr,"test2 - unknown state %d\n",state);
- return(-1);
- }
- }
-
-
- /* This is the action procedure for the third test. It performs the next
- * part of the test, increments the state variables, and returns. If all
- * of the tests have been finished, it returns 0, otherwise it returns 1.
- *
- * Action performed depends on the variable state, which can be:
- * 0 - Create initial files.
- * 1 - Randomly choose file and action and perform it.
- */
-
- int test3_action()
- {
- static long repeat = 0; /* times test has been repeated */
- static state = 0; /* next action to do */
- static fd[2];
-
- repeat++;
- if(repeat > TEST3_REPEATS) return(0);
- if(repeat == TEST3_REPEATS){
- sclose(fd[0]);
- sclose(fd[1]);
- sunlink(TEST3_FILE1NAME);
- sunlink(TEST3_FILE2NAME);
- return(1);
- }
- if(state==0){ /* setup */
- long bytesleft = 0; /* bytes to transfer */
- unsigned xfer;
-
- /* create the first file */
- fd[0] = sopen(TEST3_FILE1NAME,
- O_RDWR | O_CREAT | O_BINARY | O_TRUNC,0666);
- for(bytesleft = TEST3_FILE1SIZE; bytesleft>0;){
- xfer = min(BUFSIZE,bytesleft);
- swrite(fd[0],buf,xfer);
- bytesleft -= xfer;
- }
-
- fd[1] = sopen(TEST3_FILE2NAME,
- O_RDWR | O_CREAT | O_BINARY | O_TRUNC,0666);
- for(bytesleft = TEST3_FILE2SIZE; bytesleft>0;){
- xfer = min(BUFSIZE,bytesleft);
- swrite(fd[1],buf,xfer);
- bytesleft -= xfer;
- }
- state++;
- }
- else{
- int file = rnd(2);
- int action = rnd(2);
- long pos;
-
- /* Choose a random record, then the record's offset */
-
- pos = rnd(test3_lens[file] / test3_xfer[file]);
- pos *= test3_xfer[file];
-
-
- slseek(fd[file],pos,0);
- if(action==0){
- swrite(fd[file],buf,test3_xfer[file]);
- }
- else{
- sread(fd[file],buf,test3_xfer[file]);
- }
- }
- return(1);
- }
-
-
- /* test4:
- * Make 1000 dirs, and create 10 files in each. (Using creat(2)).
- * Open and close each one, directory-wise.
- *
- * State 0 - create directories and files
- * State 1 - open/close file
- * state 2 - delete files and directories
- */
-
- char *test4_dirname(dir)
- int dir;
- {
- static char buf[100];
-
- sprintf(buf,TEST4_DIRNAME, dir);
- return(buf);
- }
-
- char *test4_filename(dir,file)
- int dir,file;
- {
- static char buf[100];
-
- sprintf(buf,TEST4_DIRNAME "/" TEST4_FILENAME,dir,file);
- return(buf);
- }
-
- test4_action()
- {
- static state = 0; /* major state variable */
- static long fstate = 0; /* dir/file counter */
- int dir,file;
-
- dir = fstate / TEST4_FILES;
- file = fstate % TEST4_FILES;
-
- switch(state){
- case 0:
- if(file==0){
- smkdir(test4_dirname(dir));
- }
- else{
- sclose(screat(test4_filename(dir,file),
- S_IREAD | S_IWRITE));
- }
- break;
-
- case 1:
- if(file>0){
- sclose(sopen(test4_filename(dir,file),
- O_RDONLY | O_BINARY,0666));
- }
- break;
-
- case 2:
- if(++file==TEST4_FILES){
- srmdir(test4_dirname(dir));
- }
- else{
- sunlink(test4_filename(dir,file));
- }
- break;
- case 3: return(0);
- }
- if(++fstate >= TEST4_DIRS * TEST4_FILES){
- fstate = 0;
- state++;
- }
- return(1);
- }
-
-
-
-
- char *test5_dirname(dir)
- int dir;
- {
- static char buf[100];
-
- sprintf(buf,TEST5_DIRNAME, dir);
- return(buf);
- }
-
- char *test5_filename(dir,file)
- int dir,file;
- {
- static char buf[100];
-
- sprintf(buf,TEST5_DIRNAME "/" TEST5_FILENAME,dir,file);
- return(buf);
- }
-
- test5_action()
- {
- static state = 0; /* major state variable */
- static long fstate = 0; /* dir/file counter */
- int dir,file;
-
- file = fstate / TEST5_DIRS;
- dir = fstate % TEST5_DIRS;
-
- switch(state){
- case 0:
- if(file==0){
- smkdir(test5_dirname(dir));
- }
- else{
- sclose(screat(test5_filename(dir,file),
- S_IREAD | S_IWRITE));
- }
- break;
-
- case 1:
- if(file>0){
- sclose(sopen(test5_filename(dir,file),
- O_RDONLY | O_BINARY,0666));
- }
- break;
-
- case 2:
- if(++file==TEST5_FILES){
- srmdir(test5_dirname(dir));
- }
- else{
- sunlink(test5_filename(dir,file));
- }
- break;
- case 3: return(0);
- }
- if(++fstate >= TEST5_DIRS * TEST5_FILES){
- fstate = 0;
- state++;
- }
- return(1);
- }
-
-
- test6_action()
- {
- int test = rnd(MAXTESTS-1);
- int test0;
-
- test0 = test; /* remember which test we started at */
-
- do{
- if((*action[test])()) return(1);/* if we did something, ret */
- test = (test+1) % (MAXTESTS-1); /* choose next test */
- if(test==test0) return(0); /* if we wrapped, none left */
- } while(1);
- }
-
- main(argc,argv)
- char **argv;
- {
- long starttime,stoptime;
- long testclick = 0;
- int test;
- unsigned i;
-
- for(i=0;i<BUFSIZE;i++){
- buf[i] = i;
- }
-
- while(argv[1][0]=='-'){
- if(!strcmp(argv[1],"-d")){
- debug++;
- argv++;
- argc--;
- }
- }
-
- if(argc<2){
- fprintf(stderr,"usage: %s [-d] <test> where tests are:\n",
- argv[0]);
- fprintf(stderr,"\t1 - Image store test.\n");
- exit(1);
- }
-
- test = atoi(argv[1]);
- if(argc>2){
- TEST5_DIRS = atoi(argv[2]);
- }
- if(test<1 || test>MAXTESTS){
- fprintf(stderr,"%d is out of range\n",test);
- exit(1);
- }
-
- time(&starttime);
-
- while((*action[test-1])()){
- if((++testclick % 20)==0){
- printf("%ld...",testclick);
- }
- }
-
- time(&stoptime);
-
- printf("\n\nTest %d total time = %ld\n",test,stoptime-starttime);
- if(test==5) printf("TEST5_DIRS = %d\n",TEST5_DIRS);
- puts("");
- exit(0);
- }
-