Example #1
0
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;
}
Example #2
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;
}
Example #3
0
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;
}
Example #4
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;
}