_THE FIVE LEVELS OF RAID_ by Mike Wiebel and Steve Johnson [LISTING ONE] /* sled.c */ #include #include #include #define HMSEC(x) ((TIME)((x))) /* 1.0e-05 second */ #define MSEC(x) ((TIME)(100.0 * (x))) /* milli second */ #define SEC(x) MSEC((1000.0 * (x))) /* second */ #define MINUTE(x) SEC((60.0 * (x))) /* minute */ #define HOUR(x) MINUTE((60.0 * (x))) #define NUM_DISKS 1 /* num. disks in simulation */ #define NUM_FE 1L /* num. front end channels */ #define NUM_BE 1L /* num. back end channels */ #define SEEK_TIME 3.83 /* avg. num. of milliseconds spent seeking */ #define LATENCY 14.22 /* milliseconds required for one rotation */ #define NUM_CYLINDERS 1113 /* num. cylinders on disk */ #define TRACKS_PER_CYL 15 /* num. tracks per cylinder */ SS_PTR cu; /* CSIM control unit pointer */ SS_PTR disk_drive; /* CSIM disk drive pointer */ MS_PTR fe_bus; /* CSIM front end channel pointer */ MS_PTR be_bus; /* CSIM back end channel pointer */ static long track=0L; /* current track backing */ static int cylinder=0; /* current cylinder backing */ static long tot_tracks=0L; /* total tracks backed */ void backup_status(done) int *done; { /* determine if this disk drive is backed up. */ track++; tot_tracks++; if (tot_tracks == NUM_DISKS * NUM_CYLINDERS * TRACKS_PER_CYL) *done = 1; } ECODE seek() { long num_fe; /* num. front end channels available */ if(track == 1){ /* first track requires seek */ XacAdvExponen(MSEC(SEEK_TIME)); } if(track == TRACKS_PER_CYL){ XacAdvance(MSEC(LATENCY));/* switch cylinder and rotate */ track = 0; cylinder++; } /* if channel is available transmit data; else rotational delay */ MAvail(fe_bus,&num_fe); while(!num_fe){ XacAdvance(MSEC(LATENCY)); MAvail(fe_bus,&num_fe); /* sled.c - 2 */ } return(SUCCESS); } ECODE send_data() { double xfr_time; /* transfer data back to host */ xfr_time = LATENCY; MSeize(fe_bus,1L); XacAdvance(MSEC(xfr_time)); MRelease(fe_bus,1L); return(SUCCESS); } int sim_main(argc, argv) int argc; char *argv[]; { int done=0; int i; /* configure system and set up CSIM statistics */ SServer(&cu,"control unit statistics"); SServer(&disk_drive,"disk drive statistics"); MServer(&fe_bus,NUM_FE,"front end channels"); MServer(&be_bus,NUM_BE,"back end channels"); /* set simulation time */ SimWarmUp(0,0); SimRun(MINUTE(30),1); /* simulate backup */ SSeize(disk_drive); SSeize(cu); MSeize(be_bus,1L); for(i=0; i #include #include #define HMSEC(x) ((TIME)((x))) /* hund.milli second */ #define MSEC(x) ((TIME)(100.0 * (x))) /* milli second */ #define SEC(x) MSEC((1000.0 * (x))) /* seconds */ #define MINUTE(x) SEC((60.0 * (x))) /* minutes */ #define HOUR(x) MINUTE((60.0 * (x))) #define NUM_DISKS 1 /* one disk; other disk is mirror */ #define NUM_FE 2L /* num. front end channels */ #define NUM_BE 2L /* num. back end channels */ #define NUM_CU 2L /* num. of control units */ #define SEEK_TIME 3.83 /* avg. num. of milliseconds spent seeking */ #define LATENCY 14.22 /* avg. num. milliseconds spent seeking */ #define NUM_CYLINDERS 2226 #define TRACKS_PER_CYL 15 MS_PTR cu; /* CSIM control unit pointer */ MS_PTR disk_drive; /* CSIM disk drive pointer */ MS_PTR fe_bus; /* CSIM front end channel pointer */ MS_PTR be_bus; /* CSIM back end channel pointer */ Q_PTR tsend; static long track=0L; static int curr_cylinder=0; void backup_status(done) int *done; { /* determine if this disk drive is backed up. */ track++; if (track == TRACKS_PER_CYL){ track = 0; curr_cylinder++; } if (curr_cylinder == NUM_CYLINDERS * NUM_DISKS) *done = 1; } ECODE seek(cylinder_backing) int *cylinder_backing; { long num_fe; if(curr_cylinder == 0 && track == 1){ /* first track requires seek */ XacAdvExponen(MSEC(SEEK_TIME)); } if(*cylinder_backing != curr_cylinder){ XacAdvance(MSEC(LATENCY)); *cylinder_backing = curr_cylinder; } return(SUCCESS); } /* lvl1.c - 2 */ ECODE send_data() { double xfr_time; /* transfer data back to host */ xfr_time = LATENCY; MSeize(fe_bus,1L); XacAdvance(MSEC(xfr_time)); MRelease(fe_bus,1L); return(SUCCESS); } int sim_main(argc, argv) int argc; char *argv[]; { XAC_PTR xp; BOOLEAN orig; static int done=0; int cylinder_backing=0; int i; /* configure system and set up CSIM utilities */ MServer(&disk_drive,2L,"Disk drive server statistics"); MServer(&cu,NUM_CU,"Control unit server statistics"); MServer(&fe_bus,NUM_FE,"front end channel statistics"); MServer(&be_bus,NUM_BE,"back end channel statistics"); Queue(&tsend,"Time to send data"); /* set simulation time */ SimWarmUp(0,0); SimRun(MINUTE(17),1); /* simulate backup */ XacSplit(&xp,&orig); /* allow each disk subsys to transfer */ MSeize(cu,1L); MSeize(be_bus,1L); MSeize(disk_drive,1L); for(i=0; i #include #define HMSEC(x) ((TIME)((x))) /* 1.0e-05 second */ #define MSEC(x) ((TIME)(100.0 * (x))) /* milli second */ #define SEC(x) MSEC((1000.0 * (x))) /* second */ #define MINUTE(x) SEC((60.0 * (x))) /* minute */ #define HOUR(x) MINUTE((60.0 * (x))) #define GRP_SIZE 4 /* no. data disks in parity group */ #define NUM_CHECK 1 /* no. check disks in group */ #define NUM_CHAN 2L /* no. of channels */ #define NUM_BUSS 5L /* no. busses */ #define SEEK_TIME 11.5 /* avg. num. of milliseconds spent seeking */ #define LATENCY 16.66 /* milliseconds required for one rotation */ #define TRACK_CAPACITY 40.0 /* capacity in KB */ #define XFR_RATE 10000.0 /* KB transferred per sec */ #define NUM_CYLINDERS 1900 /* no. useable cylinders on device */ #define TRACKS_PER_CYL 19 /* no. tracks per cylinder */ #define SWITCH_TIME 4 /* milliseconds */ SS_PTR raid_cu; /* CSIM RAID control unit pointer */ MS_PTR data_disk; /* CSIM array of data disks pointer */ SS_PTR check_disk; /* CSIM check disk pointer */ MS_PTR buss; /* CSIM array of busses pointer */ MS_PTR channel; /* CSIM array of channels pointer */ ECODE seek(track_tally,original,track_count) long track_tally; BOOLEAN original; int *track_count; { if (original){ SSeize(check_disk); } else{ MSeize(data_disk,1L); } if (!track_tally){ XacAdvExponen(MSEC(SEEK_TIME)); } if (!(*track_count) && track_tally){/* switch cylinders */ XacAdvance(MSEC(SWITCH_TIME)); } (*track_count)++; if (*track_count == TRACKS_PER_CYL) *track_count = 0; if (original){ SRelease(check_disk); } else{ MRelease(data_disk,1L); } return(SUCCESS); } /* lvl3.c - 2 */ ECODE transfer() { double xfr_time; XAC_PTR xp; BOOLEAN orig; /* send data to control unit */ MSeize(buss,1L); XacAdvance(MSEC(LATENCY)); MRelease(buss,1L); /* send data to host */ XacSplit(&xp,&orig); if (!orig){ xfr_time = TRACK_CAPACITY/XFR_RATE; MSeize(channel,1L); XacAdvance(SEC(xfr_time)); MRelease(channel,1L); XacTerminate(); } return(SUCCESS); } int sim_main(argc, argv) int argc; char *argv[]; { static int done=0; /* flag indicating completion */ int track_count=0; long track_tally=0; /* count of tracks backed up */ long backup_goal; /* total number of tracks to back up */ int i; /* counter */ XAC_PTR xp; /* CSIM transaction pointer */ BOOLEAN original; /* flag indicating presence of original xac */ /* configure system and set up CSIM */ SServer(&raid_cu,"Control unit server statistics"); SServer(&check_disk,"check disk statistics"); MServer(&data_disk,GRP_SIZE,"data disk statistics"); MServer(&buss,NUM_BUSS,"buss statistics"); MServer(&channel,NUM_CHAN,"channel statistics"); /* set simulation period */ SimWarmUp(0,0); SimRun(MINUTE(30),1); for(i=0; i #include #include #define HMSEC(x) ((TIME)((x))) /* 1.0e-05 second */ #define MSEC(x) ((TIME)(100.0 * (x))) /* milli second */ #define SEC(x) MSEC((1000.0 * (x))) /* second */ #define MINUTE(x) SEC((60.0 * (x))) /* minute */ #define HOUR(x) MINUTE((60.0 * (x))) #define GRP_SIZE 50 /* no. data disks in parity group */ #define NUM_CHAN 2L /* no. of channels */ #define NUM_BUSS 50L /* no. busses */ #define SEEK_TIME 11.5 /* avg. num. of milliseconds spent seeking */ #define LATENCY 16.66 /* milliseconds required for one rotation */ #define TRACK_CAPACITY 40.0 /* capacity in KB */ #define XFR_RATE 10000.0 /* KB transferred per sec */ #define NUM_CYLINDERS 1900 /* no. useable cylinders on device */ #define TRACKS_PER_CYL 19 /* no. tracks per cylinder */ #define SWITCH_TIME 4 /* milliseconds */ #define BUF_SZ 50 /* number of tracks buffer will hold */ SS_PTR raid_cu; /* CSIM RAID control unit pointer */ SAS_PTR data_disk; /* CSIM array of data disks pointer */ MS_PTR buss; /* CSIM array of busses pointer */ MS_PTR channel; /* CSIM array of channels pointer */ long buffer[BUF_SZ]; /* RAID control unit buffer */ long update[BUF_SZ]; /* RAID buffer lock */ static long last_buf=0L; /* last track written to buffer */ void buffer_search(track,bingo,slot) long track; int *bingo; int *slot; { int i; *bingo = 0; for(i=0; i= GRP_SIZE) number -= GRP_SIZE; return(number); } ECODE track_get() { MSeize(buss,1L); MSeize(channel,1L); XacAdvance(MSEC(LATENCY)); XacAdvance(MSEC(1)); MRelease(channel,1L); MRelease(buss,1L); return(SUCCESS); } ECODE update_buf(track) long track; { XAC_PTR xp; BOOLEAN orig; static int i; static int j; int slot; long next; int d_num; j = 0; for(i=0; i