int g4_load_tp(struct dm_layout_g4 *r, struct lp_list *l) { int i; ddbg_assert(r->track_len == 0); r->track_len = l->values_pop / TP_FIELDS; r->track = calloc(r->track_len, sizeof(*r->track)); for(i = 0; i < r->track_len; i++) { r->track[i].low = l->values[TP_FIELDS*i]->v.i; r->track[i].high = l->values[TP_FIELDS*i+1]->v.i; r->track[i].spt = l->values[TP_FIELDS*i+2]->v.i; r->track[i].sw = dm_angle_dtoi(1.0 / r->track[i].spt); } return 0; }
// do_idx_ent() does the hard work to measure the skews for a single // index entry. We need to determine e->off, the angular offset of // the first lbn of this instance taking the first lbn of parent as // the 0 point and e->alen, the angular offset of the i+1st instance // of e from the ith. void do_idx_ent(struct dm_disk_if *d, // diskmodel struct dm_layout_g4 *l, // root of g4 layout struct idx_ent *e, // the entry in question struct idx *parent, // The index containing e struct idx_ent *parent_e, // The entry for parent in its parent int parent_off, // Which entry we are in parent struct dsstuff *ds, // Disksim instance struct trace *t, // io trace int lbn) { // The first lbn of parent int i; int l0; int dist; double yi; double *times; double *tracetimes; // for bootstrapping off and len double off0time, len0time; int off0lbn[2], len0lbn[2]; // Work internally in floating-point, then convert back to the // integer representation at the end. double aoff = dm_angle_itod(e->off); double alen = dm_angle_itod(e->alen); double period = dm_time_itod(d->mech->dm_period(d)); // Number of instances of this entry. int quot = e->runlen / e->len; // times[i] is disksim's prediction of the amount of time to access the // first lbn of the ith instance after accessing the first instance. times = calloc(quot, sizeof(double)); // Actual times from the trace replay against the real disk. tracetimes = calloc(quot, sizeof(double)); // li[i] contains the first lbn of the ith instance of e. int *li = calloc(quot, sizeof(*li)); printf("%s() lbn %d e->lbn %d alen %f off %f quot %d\n", __func__, lbn, e->lbn, alen, aoff, quot); if(e->alen != 0 || e->off != 0) { printf("%s() already done, apparently\n", __func__); return; } // Bootstrap offset by measuring the first instance. if(e->lbn != 0) { aoff = measure_one_skew(d, ds, t, lbn, lbn + e->lbn); e->off = dm_angle_dtoi(aoff); } // Check for the end of the lbn space. if(lbn + e->lbn + e->len >= d->dm_sectors) { e->alen = dm_angle_dtoi(0.0); return; } // Bootstrap alen by measuring the skew from the first to the second // instance. alen = measure_one_skew(d, ds, t, lbn + e->lbn, lbn + e->lbn + e->len); e->alen = dm_angle_dtoi(alen); printf("first off %f len %f\n", aoff, alen); // Expand out the lbns of all of the instances. For calibration // (second pass), read in the values from the trace. To generate // the trace (first pass), time how long it takes to read the first // lbn of the ith instance after reading the last lbn on the first // track of the first instance. for(i = 1; i < quot; i++) { l0 = lbn; li[i] = l0 + e->lbn + e->len * i; adjust_lbns(d, &l0, &li[i]); if(mode == CALIB) { tracetimes[i] = get_tracetime(t, l0, li[i]); printf("%d (%d,%d) trace %f pred %f\n", i, l0, li[i], tracetimes[i], times[i]); } else { time_second_request(l0, li[i], ds, t, d); } } if(mode == GENTRACE) { return; } // Now calibrate the value. We first look at the first 2 instances, // then 4, then 8, etc, refining our estimate at each step. for(dist = 2; dist < quot ; ) { // y = a + bx; r is the correlation coeffecient. double a, b; for(i = 1; i < dist; i++) { times[i] = time_second_request(l0, li[i], ds, t, d); printf("%d (%d,%d) trace %f pred %f\n", i, l0, li[i], tracetimes[i], times[i]); } // Do a linear least squares fit of the difference between the // predicted and actual service times. The slope (b) of that line // corresponds to the error in our estimate of alen and the y // intercept corresponds to the error in our estimate of off. b = find_slope(times, tracetimes, dist, &a, period); // Adjust the instance-to-instance skew according to the fit. alen = fix_angle(alen - b / period); e->alen = dm_angle_dtoi(alen); // If e is the first instance in its parent index, its offset is // defined to be 0. Otherwise, correct according to the fit. if(e->lbn > lbn) { printf("fix aoff (%d, %d)\n", lbn, e->lbn); aoff = fix_angle(aoff - a / period); e->off = dm_angle_dtoi(aoff); } printf("alen -> %f, off -> %f (dist %d)\n", alen, aoff, dist); if(dist == quot) { break; } else if(dist * 2 >= quot) { dist = quot; } else { dist *= 2; } } free(li); free(tracetimes); free(times); return; }
int g4_load_idx(struct dm_layout_g4 *r, struct lp_list *l) { int i, j; // offset in l int loff = 0; r->idx_len = l->values_pop; r->idx = calloc(r->idx_len, sizeof(*r->idx)); for(i = 0; i < r->idx_len; i++) { int reallen = 0; struct idx *opi = &r->idx[i]; struct lp_list *li = l->values[i]->v.l; struct idx_ent *entj; loff = 0; // this is a little sloppy yields an upper bound, not an // exact number opi->ents_len = li->values_pop / IDX_FIELDS; opi->ents = calloc(opi->ents_len, sizeof(*opi->ents)); for(j = 0, entj = opi->ents; j < opi->ents_len && loff < li->values_pop; j++, entj++) { int off; entj->lbn = li->values[loff++]->v.i; entj->cyl = li->values[loff++]->v.i; entj->off = dm_angle_dtoi(li->values[loff++]->v.d); entj->len = li->values[loff++]->v.i; entj->cyllen = li->values[loff++]->v.i; entj->alen = dm_angle_dtoi(li->values[loff++]->v.d); entj->runlen = li->values[loff++]->v.i; entj->cylrunlen = li->values[loff++]->v.i; if(!strcmp(li->values[loff]->v.s, "TRACK")) { loff++; entj->childtype = TRACK; off = li->values[loff++]->v.i; ddbg_assert(off < r->track_len); entj->child.t = &r->track[off]; entj->head = li->values[loff++]->v.i; } else if(!strcmp(li->values[loff]->v.s, "IDX")) { loff++; entj->childtype = IDX; // XXX weird recursion off = li->values[loff++]->v.i; ddbg_assert(off < r->idx_len); entj->child.i = &r->idx[off]; } else { ddbg_assert(0); } reallen++; } opi->ents_len = reallen; } return 0; }
void simresult_update_mechanicalstate( int tagID, struct dm_mech_state begin, double realAngle, struct dm_pbn destpbn) { int seekResultIndex = DISKSIM_SIM_RESULT_LIST[tagID - 1].seekResultIndex; DISKSIM_SIM_RESULT_LIST[tagID - 1].seekResults[seekResultIndex].mechStateBegin = begin; DISKSIM_SIM_RESULT_LIST[tagID - 1].seekResults[seekResultIndex].mechStateBegin.theta = dm_angle_dtoi( realAngle/360.0 ); DISKSIM_SIM_RESULT_LIST[tagID - 1].seekResults[seekResultIndex].pbnDest = destpbn; }