rf_geometry.c

来自「RAIDFrame是个非常好的磁盘阵列RAID仿真工具」· C语言 代码 · 共 890 行 · 第 1/2 页

C
890
字号
    /* By first multiplying 'phys' by the sectors per track in       the current zone divided by the sectors per track in the       previous zone, we convert a given physical sector in one       zone to an equivalent physical sector in another zone. */	  phys = ((phys * z->zone.sec_per_track / previous_spt) +		  (((z->zone.num_sectors - 1) % z->zone.sec_per_track) + 		   (z->zone.track_skew * z->zone.num_cylinders *		    disk->geom->tracks_per_cyl) +		   (long) ceil( (double) z->zone.sec_per_track *			       (disk->geom->seek_constant_coeff) /			       disk->geom->revolution_time) *		   z->zone.num_cylinders)) %		     z->zone.sec_per_track;    previous_spt = z->zone.sec_per_track;    z = z->next;  }    /* The final physical sector equals the physical sector up to      the particular zone, plus the physical sector caused by the     sector offset into this zone. */  phys = ((phys * z->zone.sec_per_track / previous_spt) +	  ((sector % z->zone.sec_per_track) +	   (z->zone.track_skew * (sector / z->zone.sec_per_track)) +	   (long) ceil( (RF_TICS_t) z->zone.sec_per_track * 		       (disk->geom->seek_constant_coeff) /		       disk->geom->revolution_time) *	   (sector / (z->zone.sec_per_track * 		      disk->geom->tracks_per_cyl)))) %			z->zone.sec_per_track;      return( phys );}/* ** When each disk starts up, its index mark is a fraction (f) of a rotation ** ahead from its heads (in the direction of rotation).  The sector  ** under its heads is at a fraction f of a rotation from the index ** mark.  After T time has past, T/rotation_time revolutions have occured, so ** the sector under the heads is at a fraction FRAC(f+T/rotation_time) of a ** rotation from the index mark.  If the target block is at physical sector ** X relative to its index mark, then it is at fraction (X/sectors_per_track), ** so the rotational delay is  ** ((X/sectors_per_track)-FRAC(f+T/rotation_time)) * revolution_time ** if this is positive, otherwise it is ** (1+(X/sectors_per_track)-FRAC(f+T/rotation_time)) * revolution_time */#define FRAC(a) ( (a) - (long) floor(a) )static RF_TICS_t Delay_to(cur_time, block, disk)  RF_TICS_t        cur_time;  RF_SectorNum_t   block;  RF_DiskState_t  *disk;{  RF_TICS_t tmp;  RF_ZoneList_t *z;    long sector = block * disk->sectors_per_block;  z = disk->geom->zbr_data;  /* This while-loop finds the zone to which sector belongs. */  while (sector >= z->zone.num_sectors) {    sector = sector - z->zone.num_sectors;    z = z->next;  }    tmp = (	 (RF_TICS_t) Find_phys_sector(block,disk)/z->zone.sec_per_track	 - FRAC(disk->index_offset+cur_time/disk->geom->revolution_time)	 ) * disk->geom->revolution_time;  if( tmp < 0 ) tmp += disk->geom->revolution_time;  if( tmp < 0 ) RF_PANIC();  return( tmp );}/* Hmmm...they seem to be computing the head switch time as * equal to the track skew penalty.  Is this an approximation? * (MCH) */static RF_TICS_t Seek_time( to_cyl, to_track, from_cyl, from_track, disk )  long             to_cyl;  long             to_track;  long             from_cyl;  long             from_track;  RF_DiskState_t  *disk;{  long cyls = ABS_DIFF( from_cyl, to_cyl ) - 1;  RF_TICS_t seek = 0.0;  RF_ZoneList_t * z;    /* printf("Seek_time:  from_cyl %ld, to_cyl %ld, from_trk %ld, to_trk %ld\n",from_cyl, to_cyl, from_track, to_track); */  if( from_cyl != to_cyl ) {    z = disk->geom->zbr_data;    /* This while-loop finds the zone to which to_cyl belongs. */    while (to_cyl >= z->zone.num_cylinders) {      to_cyl = to_cyl - z->zone.num_cylinders;      z = z->next;    }        seek = disk->geom->seek_constant_coeff       + disk->geom->seek_linear_coeff * cyls	+ disk->geom->seek_sqrt_coeff * sqrt( (double) cyls ) 	  + z->zone.track_skew * disk->geom->revolution_time /	    z->zone.sec_per_track;      } else if( from_track != to_track ) {    /* from_track and to_track must lie in the same zone. */    z = disk->geom->zbr_data;    /* This while-loop finds the zone to which from_cyl belongs. */    while (from_cyl >= z->zone.num_cylinders) {      from_cyl = from_cyl - z->zone.num_cylinders;      z = z->next;    }         seek = z->zone.track_skew      * disk->geom->revolution_time	/ z->zone.sec_per_track;  }  return( seek );}static RF_TICS_t Seek(cur_time, block, disk, update)  RF_TICS_t        cur_time;  RF_SectorNum_t   block;  RF_DiskState_t  *disk;  long             update;{  long cur_cyl, cur_track;  /*    ** current location is derived from the time,   ** current track and current cylinder   **    ** update current location as you go   */    RF_ASSERT( block <= disk->last_block_index );  cur_cyl = disk->cur_cyl;  cur_track = disk->cur_track;  if (update) {    disk->cur_cyl = Find_cyl( block, disk );    disk->cur_track = Find_track( block, disk );  }  return( Seek_time( disk->cur_cyl, disk->cur_track,		    cur_cyl, cur_track, disk ) );}static RF_TICS_t Rotate(cur_time, block, disk, update)  RF_TICS_t        cur_time;  RF_SectorNum_t   block;  RF_DiskState_t  *disk;  long             update;{  /*    ** current location is derived from the time,   ** current track and current cylinder   **    ** block the process until at the appropriate block   ** updating current location as you go   */    RF_ASSERT( block <= disk->last_block_index );  return( Delay_to( cur_time, block, disk ) );}static RF_TICS_t Seek_Rotate(cur_time, block, disk, update)  RF_TICS_t        cur_time;  RF_SectorNum_t   block;  RF_DiskState_t  *disk;  long             update;{  RF_TICS_t seek, delay;  RF_ASSERT( block <= disk->last_block_index );  seek = Seek( cur_time, block, disk, update );  delay =  seek + Rotate( cur_time+seek, block, disk, update );  return( delay );}static RF_TICS_t GAP(sec_per_track, disk)  long             sec_per_track;  RF_DiskState_t  *disk;{  RF_TICS_t tmp = (disk->geom->revolution_time/(100*sec_per_track));  return (tmp);}RF_TICS_t Block_access_time(cur_time, block, numblocks, disk, update)  RF_TICS_t          cur_time;  RF_SectorNum_t     block;  RF_SectorCount_t   numblocks;  RF_DiskState_t    *disk;  long               update;{  RF_TICS_t delay = 0;  long cur = block, end = block + numblocks;  long sector, tmp;  RF_ZoneList_t * z;  /*   ** this is the same as Seek_Rotate by merit of the mapping   ** except that the access ends before the gap to the next block   */  RF_ASSERT( numblocks > 0 && end-1 <= disk->last_block_index );    while( cur < end ) {    sector = cur * disk->sectors_per_block;    z = disk->geom->zbr_data;    /* This while-loop finds the zone to which sector belongs. */    while (sector >= z->zone.num_sectors) {      sector = sector - z->zone.num_sectors;      z = z->next;    }        tmp = RF_MIN( end - cur, z->zone.sec_per_track	      - cur % z->zone.sec_per_track );    delay += tmp * disk->geom->revolution_time /      z->zone.sec_per_track - 	GAP(z->zone.sec_per_track, disk);    cur += tmp;    if( cur != end )      delay += Seek_Rotate( cur_time+delay, cur, disk, update );  }  return( delay );}static void Zero_stats(disk)  RF_DiskState_t  *disk;{  char traceFileName[64];  disk->stats.num_events = 0;  disk->stats.seek_sum = 0;  disk->stats.seekSq_sum = 0;  disk->stats.rotate_sum = 0;  disk->stats.rotateSq_sum = 0;  disk->stats.transfer_sum = 0;  disk->stats.transferSq_sum = 0;  disk->stats.access_sum = 0;  disk->stats.accessSq_sum = 0;  disk->stats.sleep_sum=0;  disk->stats.idle_sum=0;  disk->stats.rw_sum=0;  disk->stats.spinup_sum=0;  disk->stats.last_acc=0;  if (rf_diskTrace){    sprintf (traceFileName,"rf_diskTracer%dc%d\0",disk->row,disk->col);    if ( (disk->traceFile= fopen(traceFileName, "w")) == NULL) {      perror(traceFileName); RF_PANIC();}  }}static RF_TICS_t Update_stats(cur_time, seek, rotate, transfer, disk)  RF_TICS_t        cur_time;  RF_TICS_t        seek;  RF_TICS_t        rotate;  RF_TICS_t        transfer;  RF_DiskState_t  *disk;{  RF_TICS_t spinup=0;  RF_TICS_t sleep=0;  RF_TICS_t idle=0;    disk->stats.num_events++;  disk->stats.seek_sum += seek;  disk->stats.seekSq_sum += seek*seek;  disk->stats.rotate_sum += rotate;  disk->stats.rotateSq_sum += rotate*rotate;  disk->stats.transfer_sum += transfer;  disk->stats.transferSq_sum += transfer*transfer;  disk->stats.access_sum += seek+rotate+transfer;  disk->stats.accessSq_sum +=    (seek+rotate+transfer)*(seek+rotate+transfer);/*   ASSERT (cur_time - disk->stats.last_acc >= 0);  */  if (cur_time-disk->stats.last_acc>disk->geom->time_to_sleep){    idle=disk->geom->time_to_sleep;          sleep = cur_time - disk->stats.last_acc - idle;    spinup=disk->geom->time_to_spinup;    rf_globalSpinup = spinup;  }  else{    idle=cur_time - disk->stats.last_acc;  }      disk->stats.sleep_sum+=sleep;  disk->stats.idle_sum+=idle;  disk->stats.rw_sum+=seek+rotate+transfer;  disk->stats.spinup_sum+=spinup;  if (rf_diskTrace){    fprintf(disk->traceFile,"%g %g\n",disk->stats.last_acc,2.0);    fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle),2.0);    if (sleep){      fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle),1.0);      fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle+sleep),1.0);    }         if (spinup){      fprintf(disk->traceFile,"%g %g\n",(cur_time),4.0);      fprintf(disk->traceFile,"%g %g\n",(cur_time+spinup),4.0);    }     fprintf(disk->traceFile,"%g %g\n",(cur_time+spinup),3.0);    fprintf(disk->traceFile,"%g %g\n",(cur_time+spinup+seek+rotate+transfer),3.0);            }  disk->stats.last_acc=cur_time+spinup+seek+rotate+transfer;     return(spinup);}void rf_StopStats(disk, cur_time)  RF_DiskState_t  *disk;  RF_TICS_t        cur_time;{	RF_TICS_t sleep=0;	RF_TICS_t idle=0;	if (cur_time - disk->stats.last_acc > disk->geom->time_to_sleep){				sleep = cur_time - disk->stats.last_acc-disk->geom->time_to_sleep;		idle = disk->geom->time_to_sleep;				}	  	else{		idle=cur_time - disk->stats.last_acc;	}	disk->stats.sleep_sum+=sleep;	disk->stats.idle_sum+=idle;	if (rf_diskTrace){	  fprintf(disk->traceFile,"%g %g\n",disk->stats.last_acc,2.0);	  fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle),2.0);	  if (sleep){	      fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle),1.0);	      fprintf(disk->traceFile,"%g %g\n",(disk->stats.last_acc+idle+sleep),1.0);	    }	  fclose(disk->traceFile);	  }}/* Sometimes num_events is zero because the disk was failed at the start * of the simulation and never replaced.  This causes a crash on some * architectures, which is why we have the conditional. */void rf_Report_stats(  RF_DiskState_t  *disk,  long            *numEventsPtr,  RF_TICS_t       *avgSeekPtr,  RF_TICS_t       *avgRotatePtr,  RF_TICS_t       *avgTransferPtr,  RF_TICS_t       *avgAccessPtr,  RF_TICS_t       *SleepPtr,  RF_TICS_t       *IdlePtr,  RF_TICS_t       *RwPtr,  RF_TICS_t       *SpinupPtr){    *numEventsPtr = disk->stats.num_events;    if (disk->stats.num_events) {	*avgSeekPtr = disk->stats.seek_sum / disk->stats.num_events;	*avgRotatePtr = disk->stats.rotate_sum / disk->stats.num_events;	*avgTransferPtr = disk->stats.transfer_sum / disk->stats.num_events;	*avgAccessPtr = disk->stats.access_sum / disk->stats.num_events;    } else {	*avgSeekPtr = 0;	*avgRotatePtr = 0;	*avgTransferPtr = 0;	*avgAccessPtr = 0;    }    *SleepPtr = disk->stats.sleep_sum;    *IdlePtr = disk->stats.idle_sum;    *RwPtr = disk->stats.rw_sum ;    *SpinupPtr = disk->stats.spinup_sum ;}int rf_Access_time( access_time, cur_time, block, numblocks, disk, media_done_time, update )  RF_TICS_t         *access_time;  RF_TICS_t          cur_time;  RF_SectorNum_t     block;  RF_SectorCount_t   numblocks;  RF_DiskState_t    *disk;  RF_TICS_t         *media_done_time;  long               update; /* 1 => update disk state, 0 => don't */{	/*	 * first move to the start of the data, then sweep to the end	 */	RF_TICS_t spinup=0;	RF_TICS_t seek = Seek( cur_time, block, disk, update );	RF_TICS_t rotate =  Rotate( cur_time+seek, block, disk, update );	RF_TICS_t transfer = Block_access_time( cur_time+seek+rotate, block,				numblocks, disk, update );	if (update) spinup=Update_stats(cur_time, seek, rotate, transfer, disk );	*media_done_time = seek+rotate+transfer;	*access_time =( seek+rotate+transfer+spinup);	return(0);}/* added to take into account the fact that maping code acounts for the disk label */void rf_GeometryDoReadCapacity(disk, numBlocks, blockSize)  RF_DiskState_t    *disk;  RF_SectorCount_t  *numBlocks;  int               *blockSize;{	*numBlocks= (disk->last_block_index + 1 )-rf_protectedSectors;			*blockSize= (disk->sectors_per_block*512 );		/* in bytes */}/* END GEOMETRY ROUTINES **********************************************/static void rf_DiskParam(numCyls, minSeek, avgSeek, maxSeek, a, b, c)  long        numCyls;  RF_TICS_t   minSeek;  RF_TICS_t   avgSeek;  RF_TICS_t   maxSeek;  RF_TICS_t  *a;  RF_TICS_t  *b;  RF_TICS_t  *c;{    if (minSeek == avgSeek && minSeek == maxSeek) {	*a = 0.0; *b = 0.0; *c = minSeek;    } else {	*a = ( 15 * avgSeek - 10 * minSeek - 5 * maxSeek ) / ( 3 * sqrt( (double) numCyls ));	*b = ( 7 * minSeek + 8 * maxSeek - 15 * avgSeek ) / ( 3 * numCyls );	*c = minSeek;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?