rf_geometry.c

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

C
890
字号
/* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Mark Holland * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//*  * Changes: *	10/24/91  Changes to support disk bus contention model *	(MCH)	  1.  Added media_done_time param to Access_time() * *	08/18/92  Geometry routines have been modified to support zone-bit  *		  recording. *	(AS)	  1.  Each routine which originally referenced the variable *		      'disk->geom->sectors_per_track' has been modified,  *		      since the number of sectors per track varies on disks *		      with zone-bit recording. *//* $Locker:  $ * $Log: rf_geometry.c,v $ * Revision 1.18  1996/08/11  00:40:57  jimz * fix up broken comment * * Revision 1.17  1996/07/28  20:31:39  jimz * i386netbsd port * true/false fixup * * Revision 1.16  1996/07/18  22:57:14  jimz * port simulator to AIX * * Revision 1.15  1996/06/07  21:33:04  jimz * begin using consistent types for sector numbers, * stripe numbers, row+col numbers, recon unit numbers * * Revision 1.14  1996/06/05  18:06:02  jimz * Major code cleanup. The Great Renaming is now done. * Better modularity. Better typing. Fixed a bunch of * synchronization bugs. Made a lot of global stuff * per-desc or per-array. Removed dead code. * * Revision 1.13  1996/05/30  23:22:16  jimz * bugfixes of serialization, timing problems * more cleanup * * Revision 1.12  1996/05/30  11:29:41  jimz * Numerous bug fixes. Stripe lock release code disagreed with the taking code * about when stripes should be locked (I made it consistent: no parity, no lock) * There was a lot of extra serialization of I/Os which I've removed- a lot of * it was to calculate values for the cache code, which is no longer with us. * More types, function, macro cleanup. Added code to properly quiesce the array * on shutdown. Made a lot of stuff array-specific which was (bogusly) general * before. Fixed memory allocation, freeing bugs. * * Revision 1.11  1996/05/24  22:17:04  jimz * continue code + namespace cleanup * typed a bunch of flags * * Revision 1.10  1996/05/23  00:33:23  jimz * code cleanup: move all debug decls to rf_options.c, all extern * debug decls to rf_options.h, all debug vars preceded by rf_ * * Revision 1.9  1996/05/18  19:51:34  jimz * major code cleanup- fix syntax, make some types consistent, * add prototypes, clean out dead code, et cetera * * Revision 1.8  1995/12/12  18:10:06  jimz * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT * fix 80-column brain damage in comments * * Revision 1.7  1995/12/01  18:29:34  root * added copyright info * */#include "rf_types.h"#include "rf_geometry.h"#include "rf_raid.h"#include "rf_general.h"#include "rf_debugMem.h"#define DISK_DB "disk_db"#define DISK_NAME "HP2247"#define ABS_DIFF(a,b) ( ((a)>(b)) ? ((a)-(b)) : ((b)-(a)) )static RF_GeometryList_t *geom_list = (RF_GeometryList_t *) NULL;RF_TICS_t rf_globalSpinup = 1.5;#define NM_LGTH 80#define NM_PATN " %80s"static RF_GeometryList_t *Fetch_geometry_db(FILE *fd);static void Format_disk(RF_DiskState_t *disk, long sectors_per_block);static long Find_cyl(RF_SectorNum_t block, RF_DiskState_t *disk);static long Find_track(RF_SectorNum_t block, RF_DiskState_t *disk);static long Find_phys_sector(RF_SectorNum_t block, RF_DiskState_t *disk);static RF_TICS_t Delay_to(RF_TICS_t cur_time, RF_SectorNum_t block,	RF_DiskState_t *disk);static RF_TICS_t Seek_time(long to_cyl, long to_track, long from_cyl,	long from_track, RF_DiskState_t *disk);static RF_TICS_t Seek(RF_TICS_t cur_time, RF_SectorNum_t block,	RF_DiskState_t *disk, long update);static RF_TICS_t Rotate(RF_TICS_t cur_time, RF_SectorNum_t block,	RF_DiskState_t *disk, long update);static RF_TICS_t Seek_Rotate(RF_TICS_t cur_time, RF_SectorNum_t block,	RF_DiskState_t *disk, long update);static RF_TICS_t GAP(long sec_per_track, RF_DiskState_t *disk);static RF_TICS_t Block_access_time(RF_TICS_t cur_time, RF_SectorNum_t block,	RF_SectorCount_t numblocks, RF_DiskState_t *disk, long update);static void Zero_stats(RF_DiskState_t *disk);static RF_TICS_t Update_stats(RF_TICS_t cur_time, RF_TICS_t seek, RF_TICS_t rotate,	RF_TICS_t transfer, RF_DiskState_t *disk);static void rf_DiskParam(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);static RF_GeometryList_t *Fetch_geometry_db(fd)  FILE  *fd;{  long ret, lineno;  char name[NM_LGTH], title[20];  RF_GeometryList_t * list = (RF_GeometryList_t *) NULL,  ** next_ptr = & list;    if( RF_MAX_DISKNAME_LEN<NM_LGTH ) RF_PANIC();  lineno = 0;  while( (ret = fscanf( fd, " %20s", title )) != EOF ) {    float tmp_f1, tmp_f2, tmp_f3, tmp_f4;    float tmp_f5=0.0;    float tmp_f6=0.0;     RF_Geometry_t *g;    long i, x, y, z, num_cylinders;    RF_ZoneList_t ** znext_ptr;    if( ret == 1 && strncmp( "enddisk", title, 8 ) == 0 ) break;    RF_Calloc(*next_ptr, 1, sizeof(RF_GeometryList_t), (RF_GeometryList_t *));    (*next_ptr)->next = (RF_GeometryList_t *) NULL;    RF_Calloc(g, 1, sizeof(RF_Geometry_t), (RF_Geometry_t *));    (*next_ptr)->disk = g;    next_ptr = &( (*next_ptr)->next ); /*prep for next iteration */    lineno++;    if (fscanf( fd, NM_PATN, name ) != 1) {      fprintf(stderr,"Disk DB Error: Can't get disk name from disk db\n");      fprintf(stderr,"lineno=%d\n", lineno);      fprintf(stderr,"name=\"%s\"\n", name);      exit(1);    }    lineno++;    if ( (fscanf(fd, " tracks per cylinder %ld", &(g->tracks_per_cyl)) != 1) || g->tracks_per_cyl <= 0) {		    fprintf(stderr,"Disk DB Error: Missing or invalid tracks/cyl for disk %s\n", name); exit(1);		  }    lineno++;    if ( (fscanf(fd, " number of disk zones %ld", &(g->num_zones)) != 1) || g->num_zones <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid number of zones for disk %s\n", name); exit(1);    }                /* This section of code creates the linked list which       contains the disk's zone information. */    g->zbr_data = (RF_ZoneList_t *) NULL;    znext_ptr = &(g->zbr_data);    num_cylinders = 0;        /* This for-loop reads in the cylinder count, the sectors       per track, and track skew for each zone on the disk. */    for (i=1; i <= g->num_zones; i++) {      lineno++;      if ( (fscanf(fd, " number of cylinders in zone %ld", &x) != 1) || x < 1) {	fprintf(stderr,"Disk DB Error: Zone %ld: Missing or invalid cyls/zone for disk %s\n", i, name); exit(1);      }      lineno++;      if ( (fscanf(fd, " sectors per track in zone %ld", &y) != 1) || y < 1 ) {	fprintf(stderr,"Disk DB Error: Zone %ld: Missing or invalid sectors/track for disk %s\n", i, name); exit(1);      }      lineno++;      if ( (fscanf(fd, " track skew in zone %ld", &z) != 1) || z < 0 ) {	fprintf(stderr,"Disk DB Error: Zone %ld: Missing or invalid track skew for disk %s\n",i, name); exit(1);      }      RF_Calloc(*znext_ptr, 1, sizeof(RF_ZoneList_t), (RF_ZoneList_t *));      (*znext_ptr)->next = (RF_ZoneList_t *) NULL;      (*znext_ptr)->zone.num_cylinders = x;      (*znext_ptr)->zone.sec_per_track = y;      (*znext_ptr)->zone.track_skew = z;      (*znext_ptr)->zone.num_sectors = 	(*znext_ptr)->zone.num_cylinders *	  g->tracks_per_cyl *	    (*znext_ptr)->zone.sec_per_track;      znext_ptr = &((*znext_ptr)->next);      num_cylinders = num_cylinders + x;    } /* End of for-loop */        lineno++;    if ( (fscanf(fd, " revolution time %f", &tmp_f1) != 1) || tmp_f1 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid revolution time for disk %s\n",name); exit(1);    }    lineno++;    if ( (fscanf(fd, " 1 cylinder seek time %f", &tmp_f2 ) != 1) || tmp_f2 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid 1-cyl seek time for disk %s\n",name); exit(1);    }    lineno++;    if ( (fscanf(fd, " max stroke seek time %f", &tmp_f3) != 1) || tmp_f3 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid max seek time for disk %s\n",name); exit(1);    }    lineno++;    if ( (fscanf(fd, " average seek time %f", &tmp_f4) != 1) || tmp_f4 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid avg seek time for disk %s\n",name); exit(1);    }    lineno++;    if ( (fscanf(fd, " time to sleep %f", &tmp_f5) != 1) || tmp_f4 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid time to sleep for disk %s\n",name); exit(1);		}    lineno++;    if ( (fscanf(fd, " time to spinup %f", &tmp_f6) != 1) || tmp_f4 <= 0) {      fprintf(stderr,"Disk DB Error: Missing or invalid time to sleep for disk %s\n",name); exit(1);    }       strcpy( g->disk_name, name );    g->revolution_time = tmp_f1;    g->seek_one_cyl = tmp_f2;    g->seek_max_stroke = tmp_f3;    g->seek_avg = tmp_f4;    g->time_to_sleep = tmp_f5;    g->time_to_spinup = tmp_f6;    /* convert disk specs to seek equation coeff */    rf_DiskParam( num_cylinders, g->seek_one_cyl,	      g->seek_avg, g->seek_max_stroke,	      &g->seek_sqrt_coeff, &g->seek_linear_coeff,	      &g->seek_constant_coeff );  }  return( list );}static void Format_disk(disk, sectors_per_block)  RF_DiskState_t  *disk;  long             sectors_per_block;{  long sector_count = 0;  RF_ZoneList_t *z;  if( disk == (RF_DiskState_t *) NULL ) RF_PANIC();  if( disk->geom == (RF_Geometry_t *) NULL ) RF_PANIC();  if( sectors_per_block <=0 ) RF_PANIC();    disk->sectors_per_block = sectors_per_block;  z = disk->geom->zbr_data;  /* This while-loop visits each disk zone and computes the total     number of sectors on the disk. */  while (z != (RF_ZoneList_t *) NULL) {    sector_count = sector_count + (z->zone.num_cylinders * 				   disk->geom->tracks_per_cyl * 				   z->zone.sec_per_track);    z = z->next;  }    disk->last_block_index = (sector_count / sectors_per_block) - 1;}void rf_InitDisk( disk, disk_db, disk_name, init_cyl, init_track, init_offset, row, col)  RF_DiskState_t  *disk;  char            *disk_db;  char            *disk_name;  long            init_cyl;  long            init_track;  RF_TICS_t       init_offset;  int             row;  int             col;{  RF_GeometryList_t *gp;  FILE *f;    RF_ASSERT( disk != (RF_DiskState_t *) NULL );    disk->cur_cyl = init_cyl;  disk->cur_track = init_track;  disk->index_offset = init_offset;  disk->geom = (RF_Geometry_t *) NULL;  disk->queueFinishTime = 0.0;  disk->lastBlock = 0;  disk->row=row;  disk->col=col;  Zero_stats(disk);  if (strncmp(disk_name,"/dev",4 )==0) strcpy(disk_name,"HP2247");    if( geom_list == (RF_GeometryList_t *) NULL ) {    f = fopen(disk_db,"r");    if (f == NULL) {      fprintf(stderr, "ERROR: RAIDframe could not open disk db %s\n", disk_db);      exit(1);    }    geom_list = Fetch_geometry_db( f );    fclose( f );  }  for( gp = geom_list; gp != (RF_GeometryList_t *) NULL; gp = gp->next ) {    RF_ASSERT( gp->disk != (RF_Geometry_t *) NULL	   &&  gp->disk->disk_name != (char *) NULL );    if( strncmp( disk_name, gp->disk->disk_name, RF_MAX_DISKNAME_LEN )       == 0 ) {      disk->geom = gp->disk;      break;    }  }  if( disk->geom == (RF_Geometry_t *) NULL ) {    fprintf( stderr, "Disk %s not found in database %s\n",	    disk_name, disk_db );    exit(1);  }    Format_disk( disk, 1 );}static long Find_cyl( block, disk )  RF_SectorNum_t   block;  RF_DiskState_t  *disk;{  RF_ZoneList_t * z;  long tmp;  long log_sector = block * disk->sectors_per_block;  long cylinder = 0;  z = disk->geom->zbr_data;  /* This while-loop finds the zone to which log_sector belongs,      computes the starting cylinder number of this zone, and      computes the sector offset into this zone. */  while (log_sector >= z->zone.num_sectors) {    log_sector = log_sector - z->zone.num_sectors;    cylinder = cylinder + z->zone.num_cylinders;    z = z->next;  }    /* The cylinder to which log_sector belongs equals the starting     cylinder number of its zone plus the cylinder offset into     the zone. */  tmp = cylinder + (log_sector / (z->zone.sec_per_track * 				  disk->geom->tracks_per_cyl));    return( tmp );}static long Find_track( block, disk )  RF_SectorNum_t   block;  RF_DiskState_t  *disk;{  RF_ZoneList_t * z;  long tmp;    long log_sector = block * disk->sectors_per_block;  long track = 0;  z = disk->geom->zbr_data;  /* This while-loop finds the zone to which log_sector belongs,     computes the starting track number of this zone, and computes     the sector offset into this zone. */  while (log_sector >= z->zone.num_sectors) {    log_sector = log_sector - z->zone.num_sectors;    track = track + (z->zone.num_cylinders * 		     disk->geom->tracks_per_cyl);    z = z->next;  }    /* The track to which log_sector belongs equals the starting     track number of its zone plus the track offset into the zone,     modulo the number of tracks per cylinder on the disk. */  tmp = (track + (log_sector / z->zone.sec_per_track)) %     disk->geom->tracks_per_cyl;    return( tmp );}/* ** The position of a logical sector relative to the index mark on any track ** is not simple.  A simple organization would be:**** 	track 0	:	0,  1,  2,  3,  ...  N-1**	track 1 :	N,N+1,N+2,N+3,  ... 2N-1**			^**			Index mark just before this point**** This is not good because sequential access of sectors N-1 then N** will require a full revolution in between (because track switch requires** a couple of sectors to recalibrate from embedded servo).  So frequently** sequentially numbered sectors are physically skewed so that the next** accessible sector after N-1 will be N (with a skew of 2)**** 	track 0	:	   0,   1,   2,   3,  ...  N-1**	track 1 :	2N-2,2N-1,   N, N+1,  ... 2N-3**			^**			Index mark just before this point**** Layout gets even more complex with cylinder boundaries.  Seek time** is A + B*M where M is the number of cylinders to seek over.  On a sequential** access that crosses a cylinder boundary, the disk will rotate for** A+B seconds, then "track skew" sectors (inter-sector gaps actually)** before it can access another sector, so the cylinder to cylinder skew** is "track skew" + CEIL( sectors_per_track*(A+B)/revolution_time ).**** So if sector 0 is 0 sectors from the index mark on the first track,** where is sector X relative to the index mark on its track?****	( ( X % sectors_per_track ) 	 basic relative position ****	+ track_skew * ( X / sectors_per_track )  skewed for each track **   **	+ CEIL( sectors_per_track*(A+B)/revolution_time )**		* ( X / sectors_per_cylinder )	 skewed more for each cyl ****	) % sectors_per_track		 wrapped around in the track *******/static long Find_phys_sector(block, disk)  RF_SectorNum_t   block;  RF_DiskState_t  *disk;{  long phys = 0;  RF_ZoneList_t * z;  long previous_spt = 1;  long sector = block * disk->sectors_per_block;    z = disk->geom->zbr_data;  /* This while-loop finds the zone to which sector belongs,     and computes the physical sector up to that zone. */  while (sector >= z->zone.num_sectors) {    sector = sector - z->zone.num_sectors;

⌨️ 快捷键说明

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