static void initialize_bands(struct dm_disk_if *d) { int j; double tmptime, rotblks; struct dm_layout_g1 *l = (struct dm_layout_g1 *)d->layout; return; // Defunct. Cook up skews if none provided in model. for (j = 0; j < l->bands_len; j++) { double period; // set tmptime to the greater of a headswitch for a read or a // write struct dm_mech_state s1 = {0,0,0}, s2 = {1,0,0}; dm_time_t t1 = d->mech->dm_seek_time(d, &s1, &s2, 0); dm_time_t t2 = d->mech->dm_seek_time(d, &s1, &s2, 1); tmptime = t1 > t2 ? t1 : t2; period = dm_time_itod(d->mech->dm_period(d)); rotblks = ((double)l->bands[j].blkspertrack) / period; // l->bands[j].firstblkangle = l->bands[j].firstblkangle / rotblks; if (l->bands[j].trackskew == -1.0) { ddbg_assert2(0, "unimplemented"); l->bands[j].trackskew = tmptime; } else if (l->bands[j].trackskew == -2.0) { ddbg_assert2(0, "unimplemented"); tmptime = (double) ((int) (tmptime * rotblks + 0.999999999)); l->bands[j].trackskew = tmptime / rotblks; } else { l->bands[j].trackskew = l->bands[j].trackskew; } // zero distance seek without a head switch // write vs. read // XXX ... based on disksim-pre3-28, every seek function returns // zero seek time for a zero distance seek! // tmptime = max(diskseektime(d, 1, 0, 0), // diskseektime(d, 1, 0, 1)); tmptime = 0; if (l->bands[j].cylskew == -1.0) { ddbg_assert2(0, "unimplemented"); l->bands[j].cylskew = tmptime; } else if (l->bands[j].cylskew == -2.0) { ddbg_assert2(0, "unimplemented"); tmptime = (double) ((int) (tmptime * rotblks + 0.99999999)); l->bands[j].cylskew = tmptime / rotblks; } else { l->bands[j].cylskew = l->bands[j].cylskew; } } }
static void DISKSIM_GLOBAL_STAT_DEFINITION_FILE_loader(int result, char *s) { char *path = lp_search_path(lp_cwd, s); if(!path) { ddbg_assert2(0, "Couldn't find statdefs file in path"); } else { statdeffile = fopen(path, "r"); ddbg_assert2(statdeffile != 0, "failed to open statdefs file!"); } }
static void cachedev_wakeup_complete (struct cache_if *c, void *d) // really struct cache_dev_event { struct cache_dev_event *desc = (struct cache_dev_event *)d; struct cache_dev *cache = (struct cache_dev *)c; ASSERT (0); #ifdef DEBUG_CACHEDEV fprintf (outputfile, "*** %f: Entered cachedev::cachedev_wakeup_complete (does nothing)\n", simtime ); #endif // ??? #if 0 switch(desc->type) { case CACHE_EVENT_READ: cache_read_continue(cache, desc); break; case CACHE_EVENT_WRITE: cache_write_continue(cache, desc); break; case CACHE_EVENT_FLUSH: (*desc->donefunc)(desc->doneparam, desc->req); addtoextraq((event *) desc); break; default: ddbg_assert2(0, "Unknown cachedev event type"); break; } #endif }
static void simpledisk_interrupt_complete (ioreq_event *curr) { #ifdef DEBUG_SIMPLEDISK fprintf (outputfile, "*** %f: simpledisk_interrupt_complete - devno %d, blkno %d, bcount %d, flags 0x%x, cause %d\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags, curr->cause ); #endif switch (curr->cause) { case RECONNECT: simpledisk_reconnect_done(curr); break; case DISCONNECT: simpledisk_disconnect_done(curr); break; case COMPLETION: simpledisk_completion_done(curr); break; default: ddbg_assert2(0, "bad event type"); break; } }
// assuming no activity, what will the state of the disk be // at some time in the future static void dm_progress_g1(struct dm_disk_if *d, struct dm_pbn *cur_state, dm_time_t time, struct dm_pbn *result_state) { ddbg_assert2(0, "unimplemented"); }
// who calls this? // in pre3-28, this seems unreachable (not sure) (bucy 2/02) void dm_mech_g1_seek_init(struct dm_disk_if *d) { double tmpfull, tmpavg, tmptime; struct dm_mech_g1 *m = (struct dm_mech_g1 *)d->mech; // XXX get rid of this FILE *outputfile = stderr; ddbg_assert2(0, "This is deprecated and/or hasn't been ported.\n"); if ((m->seektype == SEEK_3PT_CURVE) && (m->seekavg > m->seekone)) { fprintf (outputfile, "seekone %" PRIu64 ", seekavg %" PRIu64 ", seekfull %" PRIu64 "\n", m->seekone, m->seekavg, m->seekfull); tmpfull = m->seekfull; tmpavg = m->seekavg; tmptime = (double) -10.0 * m->seekone; tmptime += (double) 15.0 * m->seekavg; tmptime += (double) -5.0 * m->seekfull; // tmptime = tmptime / // (3.0 * sqrt((double) (d->dm_cyls))); m->seekavg *= (double) -15.0; m->seekavg += (double) 7.0 * m->seekone; m->seekavg += (double) 8.0 * m->seekfull; m->seekavg = m->seekavg / (double) (3 * d->dm_cyls); m->seekfull = tmptime; // fprintf (outputfile, "seekone %f, seekavg %f, seekfull %f\n", // m->seekone, m->seekavg, m->seekfull); // fprintf (outputfile, "seekone %f, seekavg %f, seekfull %f\n", // diskseektime(m, 1, 0, 1), // diskseektime(m, (d->dm_cyls / 3), 0, 1), // diskseektime(m, (d->dm_cyls - 1), 0, 1)); if ((m->seekavg < 0.0) || (m->seekfull < 0.0)) { m->seektype = SEEK_3PT_CURVE; m->seekfull = tmpfull; m->seekavg = tmpavg; } } }
static void ssd_interrupt_complete (ioreq_event *curr) { switch (curr->cause) { case RECONNECT: ssd_reconnect_done(curr); break; case DISCONNECT: ssd_disconnect_done(curr); break; case COMPLETION: ssd_completion_done(curr); break; default: ddbg_assert2(0, "bad event type"); } }
static void simpledisk_interrupt_complete (ioreq_event *curr) { // fprintf (outputfile, "Entered simpledisk_interrupt_complete - cause %d\n", curr->cause); switch (curr->cause) { case RECONNECT: simpledisk_reconnect_done(curr); break; case DISCONNECT: simpledisk_disconnect_done(curr); break; case COMPLETION: simpledisk_completion_done(curr); break; default: ddbg_assert2(0, "bad event type"); } }
int disksim_loadparams(char *inputfile, int synthgen) { int rv; int c; struct lp_tlt **tlts; int tlts_len; // register modules with libparam for(c = 0; c <= DISKSIM_MAX_MODULE; c++) { lp_register_module(disksim_mods[c]); } // diskmodel modules for(c = 0; c <= DM_MAX_MODULE; c++) { lp_register_module(dm_mods[c]); } // memsmodel modules for(c = 0; c <= MEMSMODEL_MAX_MODULE; c++) { lp_register_module(memsmodel_mods[c]); } lp_register_topoloader(disksim_topoloader); // lp_init_typetbl(); disksim->parfile = fopen(inputfile,"r"); ddbg_assert2(disksim->parfile != NULL, ("Parameter file \"%s\" cannot be opened for read access\n", inputfile)); lp_init_typetbl(); rv = lp_loadfile(disksim->parfile, &tlts, &tlts_len, inputfile, disksim->overrides, disksim->overrides_len); lp_unparse_tlts(tlts, tlts_len, outputfile, inputfile); lp_instantiate("Global", "Global"); lp_instantiate("Stats", "Stats"); // instantiate any logorgs, syncsets we find for(c = 0; c < lp_typetbl_len; c++) { if(lp_typetbl[c] != 0 && (lp_typetbl[c]->spec != 0)) { if(!strcmp(lp_lookup_base_type(lp_typetbl[c]->sub, 0), "disksim_logorg")) { iodriver_load_logorg(lp_typetbl[c]->spec); } else if(!strcmp(lp_lookup_base_type(lp_typetbl[c]->sub, 0), "disksim_syncset")) { disk_load_syncsets(lp_typetbl[c]->spec); } } } // do this *after* logorgs get instantiated! if(synthgen) { lp_instantiate("Proc", "Proc"); lp_instantiate("Synthio", "Synthio"); } fclose(disksim->parfile); return rv; }
static void disksim_topoloader(struct lp_topospec *ts, int len) { int rv = load_iodriver_topo(ts, len); ddbg_assert2(rv != 0, "Topospec load failed!"); }
static int layout_g2_loadmap(struct dm_layout_g2 *l) { FILE *fd; char junk[1024]; char countstr[16]; char *mapfile; int extentguess; int extents_ct = 0; struct dm_pbn pbn; int64_t lbn; int c,h,s,count; int lastc, lasth; int cyls, heads; int i, j; // index [cyl][head], number of extents for that track int **track_ext_counts; struct dm_layout_g2_node *curr; struct dm_layout_g2_node *track_extents; struct dm_pbn *currdefect; mapfile = lp_search_path(lp_cwd, l->mapfile); fd = fopen(mapfile, "r"); ddbg_assert3(fd != 0, ("failed to open layout mappings file %s", l->mapfile)); // ignore first 2 lines fgets(junk, sizeof(junk), fd); fgets(junk, sizeof(junk), fd); if(fscanf(fd, "%d cylinders, %*d rot, %d heads\n", &cyls, &heads) != 2) { ddbg_assert2(0, "*** error: layout_g2_loadmap: need <cyls> ... <heads>\n"); } // printf("*** layout_g2: %s %s\n", vendor, model); // printf("*** layout_g2: %d %d\n", cyls, heads); extentguess = cyls * heads * 2; // 0t tracks extentguess += extentguess/4; // if there are a lot of defects l->ltop_map = calloc(extentguess, sizeof(struct dm_layout_g2_node)); curr = &l->ltop_map[0]; l->ptol_map = calloc(cyls, sizeof(struct dm_layout_g2_cyl)); for(i = 0; i < cyls; i++) { l->ptol_map[i].surfaces = calloc(heads, sizeof(struct dm_layout_g2_surf)); } track_ext_counts = calloc(cyls, sizeof(int *)); for(i = 0; i < cyls; i++) { track_ext_counts[i] = calloc(heads, sizeof(int)); } curr = &l->ltop_map[0]; // ltop map while(fscanf(fd, "lbn %d --> cyl %d, head %d, sect %d, %s %d\n", &curr->lbn, &curr->loc.cyl, &curr->loc.head, &curr->loc.sector, countstr, &curr->len) == 6) { if(!strcmp(countstr, "seqcnt")) { curr->len++; } track_ext_counts[curr->loc.cyl][curr->loc.head]++; curr++; extents_ct++; l->ltop_map_len++; } // copy the ltop map and sort it by track track_extents = calloc(extents_ct, sizeof(struct dm_layout_g2_node)); memcpy(track_extents, l->ltop_map, extents_ct * sizeof(struct dm_layout_g2_node)); qsort(track_extents, extents_ct, sizeof(struct dm_layout_g2_node), trackcmp); // ptol map curr = &track_extents[0]; for(i = 0; i < cyls; i++) { for(j = 0; j < heads; j++) { int k; int extents_len = track_ext_counts[i][j]; l->ptol_map[i].surfaces[j].extents = calloc(extents_len, sizeof(struct dm_layout_g2_node)); l->ptol_map[i].surfaces[j].extents_len = extents_len; for(k = 0; k < extents_len; k++) { l->ptol_map[i].surfaces[j].extents[k] = *curr; curr++; } } } // free the extra extent list free(track_extents); // ddbg_assert2(extents_ct > (cyls * heads), "EOF on layout mappings file??"); // l->extents_len = extents_ct; // populate the defect list defects = calloc(extents_ct >> 3, sizeof(struct dm_pbn)); currdefect = &defects[0]; while(fscanf(fd, "Defect at cyl %d, head %d, sect %d\n", &currdefect->cyl, &currdefect->head, &currdefect->sector) == 3) { currdefect++; defects_len++; } fclose(fd); return 0; }
struct dm_layout_if * dm_layout_g1_loadparams(struct lp_block *b, struct dm_disk_if *d) { struct dm_layout_g1 *result = malloc(sizeof(*result)); memset(result, 0, sizeof(*result)); //#include "modules/dm_layout_g1_param.c" lp_loadparams(result, b, &dm_layout_g1_mod); result->disk = d; result->disk->layout = (struct dm_layout_if *)result; /* result->hdr = g1_layout_nosparing; */ /* result->hdr = g1_layout_sectpertrackspare; */ /* result->hdr = g1_layout_sectperzonespare; */ /* result->hdr = g1_layout_sectpercylspare; */ /* result->hdr = g1_layout_sectperrangespare; */ switch(result->mapping) { case LAYOUT_NORMAL: case LAYOUT_CYLSWITCHONSURF1: case LAYOUT_CYLSWITCHONSURF2: if(result->sparescheme == NO_SPARING) { result->hdr = g1_layout_nosparing; } else { if (result->sparescheme == TRACK_SPARING) { result->hdr = g1_layout_tracksparing; } else if (result->sparescheme == SECTPERTRACK_SPARING) { result->hdr = g1_layout_sectpertrackspare; } else if ((issectpercyl(result)) || (result->sparescheme == SECTATEND_SPARING)) { result->hdr = g1_layout_sectpercylspare; } else if ((result->sparescheme == SECTSPERZONE_SPARING) || (result->sparescheme == SECTSPERZONE_SPARING_SLIPTOEND)) { result->hdr = g1_layout_sectperzonespare; } else if (result->sparescheme == SECTPERRANGE_SPARING) { result->hdr = g1_layout_sectperrangespare; } else { ddbg_assert2(0, "Unknown sparing scheme"); } } break; default: ddbg_assert2(0, "Unknown lbn<->pbn scheme"); } // careful with the order here... initialize_bands(result->disk); dm_layout_g1_initialize(d); checknumblocks(result); setup_band_blknos(result); return (struct dm_layout_if *)result; }
static void * cachedev_disk_access_complete (struct cache_if *c, ioreq_event *curr) { struct cache_dev *cache = (struct cache_dev *)c; struct cache_dev_event *rwdesc = (struct cache_dev_event *)curr->buf; struct cache_dev_event *tmp = NULL; #ifdef DEBUG_CACHEDEV fprintf (outputfile, "*** %f: Entered cachedev::cache_disk_access_complete: cacheDevEventType %d, buf %p, type %d, devno %d, blkno %d, bcount %d, flags 0x%x\n", simtime, rwdesc->type, curr->buf, curr->type, curr->devno, curr->blkno, curr->bcount, curr->flags); #endif switch(rwdesc->type) { case CACHE_EVENT_READ: /* Consider writing same buffer to cache_devno, in order to populate it.*/ /* Not clear whether it is more appropriate to do it from here or from */ /* "free_block_clean" -- do it here for now to get more overlap. */ if (curr->devno == cache->real_devno) { ioreq_event *flushreq = ioreq_copy(rwdesc->req); flushreq->type = IO_ACCESS_ARRIVE; flushreq->buf = rwdesc; flushreq->flags = WRITE; flushreq->devno = cache->cache_devno; rwdesc->type = CACHE_EVENT_POPULATE_ALSO; #ifdef DEBUG_CACHEDEV fprintf (outputfile, "*** %f: Entered cachedev::cache_disk_access_complete - flushing memory cache to disk: type %d, devno %d, blkno %d, bcount %d, flags 0x%x, buf %p\n", simtime, flushreq->type, flushreq->devno, flushreq->blkno, flushreq->bcount, flushreq->flags, flushreq->buf); #endif (*cache->issuefunc)(cache->issueparam, flushreq); cache->stat.popwrites++; cache->stat.popwriteblocks += rwdesc->req->bcount; } /* Ongoing read request can now proceed, so call donefunc from get_block*/ (*rwdesc->donefunc)(rwdesc->doneparam,rwdesc->req); break; case CACHE_EVENT_WRITE: /* finished writing to cache-device */ if (curr->devno == cache->cache_devno) { cachedev_setbits (cache->validmap, curr); cachedev_setbits (cache->dirtymap, curr); if (cache->writescheme == CACHE_WRITE_THRU) { ioreq_event *flushreq = ioreq_copy(rwdesc->req); flushreq->type = IO_ACCESS_ARRIVE; flushreq->buf = rwdesc; flushreq->flags = WRITE; flushreq->devno = cache->real_devno; rwdesc->type = CACHE_EVENT_FLUSH; (*cache->issuefunc)(cache->issueparam, flushreq); cache->stat.destagewrites++; cache->stat.destagewriteblocks += rwdesc->req->bcount; } } (*rwdesc->donefunc)(rwdesc->doneparam,rwdesc->req); if (rwdesc->type != CACHE_EVENT_FLUSH) { cachedev_remove_ongoing_request (cache, rwdesc); addtoextraq ((event *) rwdesc); cache->bufferspace -= curr->bcount; } break; case CACHE_EVENT_POPULATE_ONLY: cachedev_setbits (cache->validmap, curr); cachedev_remove_ongoing_request (cache, rwdesc); addtoextraq ((event *) rwdesc); cache->bufferspace -= curr->bcount; break; case CACHE_EVENT_POPULATE_ALSO: cachedev_setbits (cache->validmap, curr); rwdesc->type = CACHE_EVENT_READ; break; case CACHE_EVENT_FLUSH: cachedev_clearbits (cache->dirtymap, curr); cachedev_remove_ongoing_request (cache, rwdesc); addtoextraq ((event *) rwdesc); cache->bufferspace -= curr->bcount; break; case CACHE_EVENT_IDLEFLUSH_READ: { ioreq_event *flushreq = ioreq_copy (curr); flushreq->type = IO_ACCESS_ARRIVE; flushreq->flags = WRITE; flushreq->devno = cache->real_devno; rwdesc->type = CACHE_EVENT_IDLEFLUSH_FLUSH; (*cache->issuefunc)(cache->issueparam, flushreq); cache->stat.destagewrites++; cache->stat.destagewriteblocks += curr->bcount; } break; case CACHE_EVENT_IDLEFLUSH_FLUSH: cachedev_clearbits (cache->dirtymap, curr); cachedev_remove_ongoing_request (cache, rwdesc); addtoextraq ((event *) rwdesc); cachedev_idlework_callback (cache, curr->devno); cache->bufferspace -= curr->bcount; break; default: ddbg_assert2(0, "Unknown cachedev event type"); break; } addtoextraq((event *) curr); /* returned cacheevent will get forwarded to cachedev_wakeup_continue... */ return(tmp); }
/* dummy */ void disksim_device_loadparams(void) { ddbg_assert2(0, "this is a dummy that isn't supposed to be called"); }
int disksim_iomap_loadparams(struct lp_block *b) { ddbg_assert2(0, "this is a dummy and isn't supposed to be called"); return 0; }
void dm_mech_g1_read_extracted_seek_curve (char *filename, int *cntptr, int **distsptr, dm_time_t **timesptr) { int rv, mat; int lineflag = 1; int count = 0, buflen = 128; int *dists; dm_time_t *times; FILE *seekfile = NULL; char linebuf[1024]; char *pathname = lp_search_path(lp_cwd, filename); if(pathname) { seekfile = fopen(pathname, "r"); } else { ddbg_assert2(0, "Seek file not found in path!"); } ddbg_assert3(seekfile != 0, ("fopen seekfile (%s) failed: %s", filename, strerror(errno))); rv = (fgets(linebuf, sizeof(linebuf), seekfile) != 0); mat = sscanf(linebuf, "Seek distances measured: %d\n", &count); if(mat == 1) { buflen = count; lineflag = 0; } dists = calloc(buflen, sizeof(*dists)); times = calloc(buflen, sizeof(*times)); do { double time, stdev; int dist; if(!lineflag) { rv = (fgets(linebuf, sizeof(linebuf), seekfile) != 0); } else { lineflag = 0; } if(rv) { mat = sscanf(linebuf, "%d, %lf, %lf\n", &dist, &time, &stdev); if(mat == 2 || mat == 3) { if(count >= buflen-1) { buflen *= 2; dists = realloc(dists, buflen * sizeof(*dists)); times = realloc(times, buflen * sizeof(*times)); } dists[count] = dist; times[count] = dm_time_dtoi(time); count++; } else { fprintf(stderr, "*** bogus line in seek curve (%s:%d): %s\n", __FILE__, __LINE__, linebuf); } } } while(rv); fclose(seekfile); *cntptr = count; *distsptr = dists; *timesptr = times; }