static void cachedev_idlework_callback (void *idleworkparam, int idledevno) { struct cache_dev *cache = (struct cache_dev *)idleworkparam; struct cache_dev_event *flushdesc; ioreq_event *flushreq; int blkno, bcount; struct ioq *queue; ASSERT (idledevno == cache->real_devno); #ifdef DEBUG_CACHEDEV fprintf(outputfile, "*** %f: Entered cachedev::cachedev_idlework_callback\n", simtime ); fflush(outputfile); #endif queue = (*cache->queuefind)(cache->queuefindparam, cache->real_devno); if (ioqueue_get_number_in_queue (queue) != 0) { return; } queue = (*cache->queuefind)(cache->queuefindparam, cache->cache_devno); if (ioqueue_get_number_in_queue (queue) != 0) { return; } if (cachedev_find_dirty_cache_blocks (cache, &blkno, &bcount) == 0) { return; } /* Just assume that bufferspace is available */ cache->bufferspace += bcount; if (cache->bufferspace > cache->stat.maxbufferspace) { cache->stat.maxbufferspace = cache->bufferspace; } flushdesc = (struct cache_dev_event *) getfromextraq(); flushdesc->type = CACHE_EVENT_IDLEFLUSH_READ; flushreq = (ioreq_event *) getfromextraq(); flushreq->buf = flushdesc; flushreq->devno = cache->cache_devno; flushreq->blkno = blkno; flushreq->bcount = bcount; flushreq->type = IO_ACCESS_ARRIVE; flushreq->flags = READ; (*cache->issuefunc)(cache->issueparam, flushreq); cache->stat.destagereads++; cache->stat.destagereadblocks += bcount; }
static void ssd_media_access_request_element (ioreq_event *curr) { ssd_t *currdisk = getssd(curr->devno); int blkno = curr->blkno; int count = curr->bcount; /* **** CAREFUL ... HIJACKING tempint2 and tempptr2 fields here **** */ curr->tempint2 = count; while (count != 0) { // find the element (package) to direct the request int elem_num = currdisk->timing_t->choose_element(currdisk->timing_t, blkno); ssd_element *elem = &currdisk->elements[elem_num]; // create a new sub-request for the element ioreq_event *tmp = (ioreq_event *)getfromextraq(); tmp->devno = curr->devno; tmp->busno = curr->busno; tmp->flags = curr->flags; tmp->blkno = blkno; tmp->bcount = ssd_choose_aligned_count(currdisk->params.page_size, blkno, count); ASSERT(tmp->bcount == currdisk->params.page_size); tmp->tempptr2 = curr; blkno += tmp->bcount; count -= tmp->bcount; elem->metadata.reqs_waiting ++; // add the request to the corresponding element's queue ioqueue_add_new_request(elem->queue, (ioreq_event *)tmp); ssd_activate_elem(currdisk, elem_num); } }
ioreq_event * ioreq_copy (ioreq_event *old) { ioreq_event *new_event = (ioreq_event *) getfromextraq(); memmove ((char *)new_event, (char *)old, sizeof(ioreq_event)); /* bcopy ((char *)old, (char *)new_event, sizeof (ioreq_event)); */ return(new_event); }
static void controller_smart_disk_data_transfer (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp = (ioreq_event *) getfromextraq(); /* fprintf (outputfile, "%f: controller_smart_disk_data_transfer: devno %d, bcount %d\n", simtime, curr->devno, curr->bcount); */ curr->time = max(device_get_blktranstime(curr), currctlr->blktranstime); tmp->time = simtime + ((double) curr->bcount * curr->time); tmp->type = CONTROLLER_DATA_TRANSFER_COMPLETE; tmp->devno = curr->devno; tmp->blkno = curr->blkno; tmp->bcount = curr->bcount; tmp->tempint2 = currctlr->ctlno; tmp->tempptr1 = curr; /* want to use the tempptr1 value for something else! */ curr->tempptr1 = tmp; curr->next = currctlr->datatransfers; curr->prev = NULL; if (curr->next) { curr->next->prev = curr; } currctlr->datatransfers = curr; addtointq((event *) tmp); }
static void DISKSIM_GLOBAL_STATISTIC_WARM_UP_TIME_loader(int result, double d) { if (! ((d >= 0))) { // foo } disksim->warmup_event = (timer_event *) getfromextraq(); disksim->warmup_event->type = TIMER_EXPIRED; disksim->warmup_event->time = d * (double) 1000.0; disksim->warmup_event->func = &disksim->timerfunc_disksim; }
static void logorg_parity_read_old_sync (logorg *currlogorg, ioreq_event *curr, int numreqs) { int i, j; depends *depend; depends *tmpdep; ioreq_event *temp; int devno = 1; depend = (depends *) getfromextraq(); depend->blkno = curr->blkno; depend->devno = curr->devno; depend->deps[0] = ioreq_copy(curr); depend->deps[0]->opid = numreqs; curr->prev = (ioreq_event *) depend; depend->numdeps = numreqs; temp = curr->next; for (i=1; i<numreqs; i++) { if (devno == 0) { depend->cont = (depends *) getfromextraq(); depend = depend->cont; } depend->deps[devno] = ioreq_copy(temp); depend->deps[devno]->opid = numreqs; devno = logorg_modulus_update(1, devno, 10); temp = temp->next; } temp = curr->next; curr->flags |= READ; for (i=1; i<numreqs; i++) { depend = (depends *) ioreq_copy(curr->prev); depend->next = (depends *) curr->prev; curr->prev = (ioreq_event *) depend; depend->blkno = temp->blkno; depend->devno = temp->devno; tmpdep = depend->cont; for (j=0; j<(numreqs/10); j++) { depend->cont = (depends *) ioreq_copy((ioreq_event *) tmpdep); tmpdep = tmpdep->cont; depend = depend->cont; } temp->flags |= READ; temp = temp->next; } }
void iodriver_interrupt_arrive (int iodriverno, intr_event *intrp) { event *tmp; ioreq_event *infoptr = (ioreq_event *) intrp->infoptr; #ifdef DEBUG_IODRIVER fprintf (outputfile, "%f, iodriver_interrupt_arrive - cause %d, blkno %lld\n", simtime, infoptr->cause, infoptr->blkno); #endif if ((iodrivers[iodriverno]->consttime == 0.0) || (iodrivers[iodriverno]->consttime == IODRIVER_TRACED_QUEUE_TIMES)) { intrp->time = iodriver_get_time_to_handle_interrupt(iodrivers[iodriverno], infoptr->cause, (infoptr->flags & READ)); iodriver_check_c700_based_status(iodrivers[iodriverno], infoptr->devno, infoptr->cause, IO_INTERRUPT_ARRIVE, infoptr->blkno); } else { intrp->time = 0.0; } if (iodrivers[iodriverno]->type == STANDALONE) { intrp->time += simtime; intrp->type = IO_INTERRUPT_COMPLETE; addtointq((event *) intrp); } else { tmp = getfromextraq(); intrp->time /= (double) 5; tmp->time = intrp->time; tmp->type = INTEND_EVENT; tmp->next = NULL; ((intr_event *)tmp)->vector = IO_INTERRUPT; intrp->eventlist = tmp; if (infoptr->cause == COMPLETION) { tmp = getfromextraq(); tmp->time = 0.0; tmp->type = IO_ACCESS_COMPLETE; tmp->next = intrp->eventlist; ((ioreq_event *)tmp)->tempptr1 = intrp; intrp->eventlist = tmp; } tmp = getfromextraq(); tmp->time = iodriver_get_time_to_respond_to_device(iodrivers[iodriverno], infoptr->cause, intrp->time); tmp->type = IO_RESPOND_TO_DEVICE; tmp->next = intrp->eventlist; ((ioreq_event *)tmp)->tempptr1 = intrp; intrp->eventlist = tmp; } }
int logorg_parity_disk (logorg *currlogorg, ioreq_event *curr, int numreqs) { depends *depend; if (curr->flags & READ) { return(numreqs); } if ((currlogorg->maptype == STRIPED) && (currlogorg->stripeunit == 0)) { curr->next = ioreq_copy(curr); curr->next->devno = currlogorg->numdisks; return(numreqs+1); } if (numreqs != 1) { fprintf(stderr, "Too many reqs at logorg_parity_disk - %d\n", numreqs); exit(1); } depend = (depends *) getfromextraq(); depend->blkno = curr->blkno; depend->devno = curr->devno; depend->numdeps = 2; depend->deps[0] = ioreq_copy(curr); depend->deps[1] = ioreq_copy(curr); depend->deps[0]->opid = 2; depend->deps[0]->devno = currlogorg->numdisks; depend->next = (depends *) getfromextraq(); depend->next->next = NULL; depend->next->blkno = curr->blkno; depend->next->devno = currlogorg->numdisks; depend->next->deps[0] = depend->deps[0]; depend->next->deps[1] = depend->deps[1]; if (currlogorg->writesync == TRUE) { depend->deps[1]->opid = 2; depend->next->numdeps = 2; } else { depend->deps[1]->opid = 1; depend->next->numdeps = 1; } curr->flags |= READ; curr->next = ioreq_copy(curr); curr->next->devno = currlogorg->numdisks; curr->prev = (ioreq_event *) depend; return(4); }
event * io_get_next_external_event (FILE *iotracefile) { ioreq_event *temp; ASSERT(io_extq == NULL); #ifdef DEBUG_IOSIM fprintf (outputfile, "Entering: io_get_next_external_event\n"); #endif temp = (ioreq_event *) getfromextraq(); switch (disksim->traceformat) { case VALIDATE: io_validate_do_stats1(); break; case HPL: io_hpl_do_stats1(); break; } temp = iotrace_get_ioreq_event(iotracefile, disksim->traceformat, temp); if (temp) { switch (disksim->traceformat) { case VALIDATE: io_validate_do_stats2 (temp); break; } temp->type = IO_REQUEST_ARRIVE; if (constintarrtime > 0.0) { temp->time = last_request_arrive + constintarrtime; last_request_arrive = temp->time; } temp->time = (temp->time * ioscale) + tracebasetime; if ((temp->time < simtime) && (!disksim->closedios)) { fprintf(stderr, "Trace event appears out of time order in trace - simtime %f, time %f\n", simtime, temp->time); fprintf(stderr, "ioscale %f, tracebasetime %f\n", ioscale, tracebasetime); fprintf(stderr, "devno %d, blkno %lld, bcount %d, flags %d\n", temp->devno, temp->blkno, temp->bcount, temp->flags); exit(1); } if (tracemappings) { io_map_trace_request(temp); } io_extq = (event *)temp; io_extq_type = temp->type; #ifdef DEBUG_IOSIM fprintf( outputfile, "*** %f: Set io_extq, type %d, devno %d, blkno %lld, bcount %d, flags %d\n", simtime, temp->type, temp->devno, temp->blkno, temp->bcount, temp->flags ); #endif } #ifdef DEBUG_IOSIM fprintf (outputfile, "Exiting: io_get_next_external_event\n"); #endif return ((event *)temp); }
static int ssd_invoke_gang_cleaning(int gang_num, ssd_t *s) { int i; int elem_num; double max_cost = 0; double elem_clean_cost; int cleaning_invoked = 0; gang_metadata *g = &s->gang_meta[gang_num]; // all the elements in the gang must be free ASSERT(g->busy == FALSE); ASSERT(g->cleaning == FALSE); // invoke cleaning on all the elements for (i = 0; i < s->params.elements_per_gang; i ++) { elem_num = gang_num * s->params.elements_per_gang + i; elem_clean_cost = _ssd_invoke_element_cleaning(elem_num, s); // stat s->elements[elem_num].stat.tot_clean_time += max_cost; if (max_cost < elem_clean_cost) { max_cost = elem_clean_cost; } } // cleaning was invoked on all the elements. we can start // the next operation on this gang only after the cleaning // gets over on all the elements. if (max_cost > 0) { ioreq_event *tmp; g->busy = 1; g->cleaning = 1; cleaning_invoked = 1; // we use the 'blkno' field to store the gang number tmp = (ioreq_event *)getfromextraq(); tmp->devno = s->devno; tmp->time = simtime + max_cost; tmp->blkno = gang_num; tmp->ssd_gang_num = gang_num; tmp->type = SSD_CLEAN_GANG; tmp->flags = SSD_CLEAN_GANG; tmp->busno = -1; tmp->bcount = -1; stat_update (&s->stat.acctimestats, max_cost); addtointq ((event *)tmp); } return cleaning_invoked; }
static void get_device_maxoutstanding (iodriver *curriodriver, device * dev) { ioreq_event *chk = (ioreq_event *) getfromextraq(); chk->busno = dev->buspath.value; chk->slotno = dev->slotpath.value; chk->devno = dev->devno; chk->type = IO_QLEN_MAXCHECK; iodriver_send_event_down_path(chk); dev->queuectlr = chk->tempint1; dev->maxoutstanding = (chk->tempint1 == -1) ? chk->tempint2 : -1; if (chk->tempint1 != -1) { curriodriver->ctlrs[chk->tempint1].maxoutstanding = chk->tempint2; curriodriver->ctlrs[chk->tempint1].maxreqsize = chk->bcount; } /* fprintf (outputfile, "Maxoutstanding: tempint1 %d, tempint2 %d, bcount %d\n", chk->tempint1, chk->tempint2, chk->bcount); */ addtoextraq((event *) chk); }
static int ssd_invoke_element_cleaning(int elem_num, ssd_t *s) { double max_cost = 0; int cleaning_invoked = 0; ssd_element *elem = &s->elements[elem_num]; // element must be free ASSERT(elem->media_busy == FALSE); max_cost = _ssd_invoke_element_cleaning(elem_num, s); // cleaning was invoked on this element. we can start // the next operation on this elem only after the cleaning // gets over. if (max_cost > 0) { ioreq_event *tmp; elem->media_busy = 1; cleaning_invoked = 1; // we use the 'blkno' field to store the element number tmp = (ioreq_event *)getfromextraq(); tmp->devno = s->devno; tmp->time = simtime + max_cost; tmp->blkno = elem_num; tmp->ssd_elem_num = elem_num; tmp->type = SSD_CLEAN_ELEMENT; tmp->flags = SSD_CLEAN_ELEMENT; tmp->busno = -1; tmp->bcount = -1; stat_update (&s->stat.acctimestats, max_cost); addtointq ((event *)tmp); // stat elem->stat.tot_clean_time += max_cost; elem->power_stat.acc_time += max_cost; ssd_dpower(s, max_cost); } return cleaning_invoked; }
void ssd_invoke_element_refresh_fcfs(int elem_num,listnode *blocks_to_refresh,ssd_t *currdisk) { int block_len = 0; int i; double cost = 0; block_len = ll_get_size(blocks_to_refresh); block_metadata *currblock = 0; listnode *currnode = 0; //for all blocks in every element. for(i=0;i<block_len;i++) { currnode = ll_get_nth_node(blocks_to_refresh,i); currblock = (block_metadata*)currnode->data; ASSERT(currblock->elem_num == elem_num); cost+= ssd_refresh_block(currblock,currdisk); //sum every cost, because we are not applying refresh in batches } ssd_element *elem = &currdisk->elements[elem_num]; if (cost > 0) { ioreq_event *tmp; elem->media_busy = TRUE; // we use the 'blkno' field to store the element number tmp = (ioreq_event *)getfromextraq(); tmp->devno = currdisk->devno; tmp->time = simtime + cost; tmp->blkno = elem_num; tmp->ssd_elem_num = elem_num; tmp->type = SSD_REFRESH_ELEMENT; tmp->flags = SSD_REFRESH_ELEMENT; tmp->busno = -1; tmp->bcount = -1; stat_update (&currdisk->stat.acctimestats, cost); addtointq ((event *)tmp); // stat elem->stat.tot_refresh_time += cost; } }
static void controller_53c700_data_transfer (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp; #ifdef DEBUG_CTLRDUMB fprintf (outputfile, "*** %f: controller_53c700_data_transfer - devno %d, blkno %d\n, bcount %d, flags 0x%x\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags ); fflush(outputfile ); /* fprintf (outputfile, "Entered controller_53c700_data_transfer - ctlno %d, devno %d, blkno %d, bcount %d\n", ctlno, curr->devno, curr->blkno, curr->bcount); */ #endif if (curr->type == DEVICE_DATA_TRANSFER_COMPLETE) { curr->time = max(device_get_blktranstime(curr), currctlr->blktranstime); } else if (curr->type == CONTROLLER_DATA_TRANSFER_COMPLETE) { fprintf(stderr, "Not yet equiped to handle controller to controller transfers\n"); exit(1); } else { fprintf(stderr, "Illegal event type at controller_53c700_data_transfer\n"); exit(1); } curr->next = currctlr->datatransfers; curr->prev = NULL; if (curr->next) { curr->next->prev = curr; } currctlr->datatransfers = curr; tmp = (ioreq_event *) getfromextraq(); tmp->time = simtime + (curr->time * (double) curr->bcount); tmp->type = CONTROLLER_DATA_TRANSFER_COMPLETE; tmp->blkno = curr->blkno; tmp->bcount = curr->bcount; tmp->tempint2 = currctlr->ctlno; tmp->tempptr1 = curr; curr->buf = tmp; addtointq((event *) tmp); }
static void logorg_parity_table_read_old (logorg *currlogorg, ioreq_event *rowhead, ioreq_event **reqlist, int opid) { ioreq_event *temp; ioreq_event *newreq; ioreq_event *prev = NULL; temp = rowhead; while (temp) { newreq = (ioreq_event *) getfromextraq(); newreq->blkno = temp->blkno; newreq->devno = temp->devno; newreq->bcount = temp->bcount; newreq->flags = temp->flags | READ; newreq->opid = opid; logorg_parity_table_insert(&reqlist[newreq->devno], newreq); newreq->prev = prev; prev = newreq; /* only the last write (the parity update) must depend on the reads */ if (temp->prev == NULL) { temp->opid = opid; } temp = temp->prev; } }
void iodriver_access_complete (int iodriverno, intr_event *intrp) { int i; int numreqs; ioreq_event *tmp; ioreq_event *del; ioreq_event *req; int devno; int skip = 0; ctlr *ctl = NULL; time_t now; if (iodrivers[iodriverno]->type == STANDALONE) { req = ioreq_copy((ioreq_event *) intrp->infoptr); } else { req = (ioreq_event *) intrp->infoptr; } #ifdef DEBUG_IODRIVER fprintf (outputfile, "*** %f: iodriver_access_complete - devno %d, blkno %d, bcount %d, read %d\n", simtime, req->devno, req->blkno, req->bcount, (req->flags & READ)); fflush(outputfile); #endif time( & now ); disksim_exectrace( "Request completion: simtime %f, devno %d, blkno %lld, bcount %d, flags %X, time %s\n", simtime, req->devno, req->blkno, req->bcount, req->flags, asctime( localtime(& now)) ); if (iodrivers[iodriverno]->devices[(req->devno)].queuectlr != -1) { int ctlrno = iodrivers[iodriverno]->devices[(req->devno)].queuectlr; ctl = &iodrivers[iodriverno]->ctlrs[ctlrno]; tmp = ctl->oversized; numreqs = 1; while (((numreqs) || (tmp != ctl->oversized)) && (tmp) && (tmp->next) && ((tmp->next->devno != req->devno) || (tmp->next->opid != req->opid) || (req->blkno < tmp->next->blkno) || (req->blkno >= (tmp->next->blkno + tmp->next->bcount)))) { // fprintf (outputfile, "oversized request in list: opid %d, blkno %lld, bcount %d\n", tmp->opid, tmp->blkno, tmp->bcount); numreqs = 0; tmp = tmp->next; } if ((tmp) && (tmp->next->devno == req->devno) && (tmp->next->opid == req->opid) && (req->blkno >= tmp->next->blkno) && (req->blkno < (tmp->next->blkno + tmp->next->bcount))) { fprintf (outputfile, "%f, part of oversized request completed: opid %d, blkno %lld, bcount %d, maxreqsize %d\n", simtime, req->opid, req->blkno, req->bcount, ctl->maxreqsize); if ((req->blkno + ctl->maxreqsize) < (tmp->next->blkno + tmp->next->bcount)) { fprintf (outputfile, "more to go\n"); req->blkno += ctl->maxreqsize; req->bcount = min(ctl->maxreqsize, (tmp->next->blkno + tmp->next->bcount - req->blkno)); goto schedule_next; } else { fprintf (outputfile, "done for real\n"); addtoextraq((event *) req); req = tmp->next; tmp->next = tmp->next->next; if (ctl->oversized == req) { ctl->oversized = (req != req->next) ? req->next : NULL; } req->next = NULL; } } } devno = req->devno; req = ioqueue_physical_access_done(iodrivers[iodriverno]->devices[devno].queue, req); if (ctl) { ctl->numoutstanding--; } // special case for validate: if (disksim->traceformat == VALIDATE) { tmp = (ioreq_event *) getfromextraq(); io_validate_do_stats1(); tmp = iotrace_validate_get_ioreq_event(disksim->iotracefile, tmp); if (tmp) { io_validate_do_stats2(tmp); tmp->type = IO_REQUEST_ARRIVE; addtointq((event *) tmp); disksim_exectrace("Request issue: simtime %f, devno %d, blkno %lld, time %f\n", simtime, tmp->devno, tmp->blkno, tmp->time); } else { disksim_simstop(); } } else if (disksim->closedios) { tmp = (ioreq_event *) io_get_next_external_event(disksim->iotracefile); if (tmp) { io_using_external_event ((event *)tmp); tmp->time = simtime + disksim->closedthinktime; tmp->type = IO_REQUEST_ARRIVE; addtointq((event *) tmp); } else { disksim_simstop(); } } while (req) { tmp = req; req = req->next; tmp->next = NULL; update_iodriver_statistics(); if ((numreqs = logorg_mapcomplete(sysorgs, numsysorgs, tmp)) == COMPLETE) { /* update up overall I/O system stats for this completed request */ ioreq_event *temp = ioqueue_get_specific_request (OVERALLQUEUE, tmp); ioreq_event *temp2 = ioqueue_physical_access_done (OVERALLQUEUE, temp); ASSERT (temp2 != NULL); addtoextraq((event *)temp); temp = NULL; if (iodrivers[iodriverno]->type != STANDALONE) { iodriver_add_to_intrp_eventlist(intrp, io_done_notify(tmp), iodrivers[iodriverno]->scale); } else { io_done_notify (tmp); } } else if (numreqs > 0) { for (i = 0; i < numreqs; i++) { del = tmp->next; tmp->next = del->next; del->next = NULL; del->type = IO_REQUEST_ARRIVE; del->flags |= MAPPED; skip |= (del->devno == devno); if (iodrivers[iodriverno]->type == STANDALONE) { del->time += simtime + 0.0000000001; /* to affect an ordering */ addtointq((event *) del); } else { iodriver_add_to_intrp_eventlist(intrp, (event *) del, iodrivers[iodriverno]->scale); } } } addtoextraq((event *) tmp); } if ((iodrivers[iodriverno]->consttime == IODRIVER_TRACED_QUEUE_TIMES) || (iodrivers[iodriverno]->consttime == IODRIVER_TRACED_BOTH_TIMES)) { if (ioqueue_get_number_in_queue(iodrivers[iodriverno]->devices[devno].queue) > 0) { iodrivers[iodriverno]->devices[devno].flag = 1; iodrivers[iodriverno]->devices[devno].lastevent = simtime; } return; } if (skip) { return; } // fprintf(outputfile, "iodriver_access_complete:: calling ioqueue_get_next_request\n"); req = ioqueue_get_next_request(iodrivers[iodriverno]->devices[devno].queue); // fprintf (outputfile, "next scheduled: req %p, req->blkno %d, req->flags %x\n", req, ((req) ? req->blkno : 0), ((req) ? req->flags : 0)); schedule_next: if (req) { req->type = IO_ACCESS_ARRIVE; req->next = NULL; if (ctl) { ctl->numoutstanding++; } if (iodrivers[iodriverno]->type == STANDALONE) { req->time = simtime; addtointq((event *) req); } else { iodriver_add_to_intrp_eventlist(intrp, (event *) req, iodrivers[iodriverno]->scale); } } }
static void logorg_parity_table_recon (logorg *currlogorg, ioreq_event *rowhead, ioreq_event **reqlist, int stripeno, int unitno, int tableadd, int opid) { ioreq_event *temp; ioreq_event *newreq; int entryno; int minblkno; int maxblkno; int lastentry; int i; int blkno; int offset; temp = rowhead; if (temp == NULL) { fprintf(stderr, "Can't have NULL rowhead at logorg_parity_table_recon\n"); exit(1); } lastentry = (stripeno + 1) * currlogorg->partsperstripe + stripeno; while (temp->prev) { temp = temp->prev; } temp->opid = opid; minblkno = temp->blkno - currlogorg->table[lastentry].blkno - tableadd; maxblkno = minblkno + temp->bcount; entryno = stripeno * currlogorg->partsperstripe + stripeno; for (i = 0; i < unitno; i++) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = currlogorg->table[entryno].devno; newreq->blkno = tableadd + minblkno + currlogorg->table[entryno].blkno; newreq->bcount = maxblkno - minblkno; newreq->flags = rowhead->flags | READ; newreq->opid = opid; logorg_parity_table_insert(&reqlist[newreq->devno], newreq); entryno++; } temp = rowhead; while (temp->prev) { blkno = currlogorg->table[entryno].blkno; offset = temp->blkno - tableadd - blkno; if (offset > minblkno) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = temp->devno; newreq->blkno = tableadd + blkno + minblkno; newreq->bcount = offset - minblkno; newreq->flags = temp->flags | READ; newreq->opid = opid; logorg_parity_table_insert(&reqlist[newreq->devno], newreq); } if ((offset + temp->bcount) < maxblkno) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = temp->devno; newreq->blkno = temp->blkno + temp->bcount; newreq->bcount = maxblkno - offset - temp->bcount; newreq->flags = temp->flags | READ; newreq->opid = opid; logorg_parity_table_insert(&reqlist[newreq->devno], newreq); } entryno++; temp = temp->prev; } for (; entryno < lastentry; entryno++) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = currlogorg->table[entryno].devno; newreq->blkno = tableadd + minblkno + currlogorg->table[entryno].blkno; newreq->bcount = maxblkno - minblkno; newreq->flags = rowhead->flags | READ; newreq->opid = opid; logorg_parity_table_insert(&reqlist[newreq->devno], newreq); } }
static void logorg_parity_table_dodeps_sync (logorg *currlogorg, ioreq_event *curr, ioreq_event **redunlist, ioreq_event **reqlist) { int i, j; depends *depend; depends *tmpdep; int opid = 0; int numdeps = 0; ioreq_event *temp; ioreq_event *deplist = NULL; int devno = 1; for (i=0; i<currlogorg->actualnumdisks; i++) { temp = redunlist[i]; while (temp) { temp->opid = curr->opid; opid++; if (temp->next == NULL) { temp->next = curr->next; curr->next = redunlist[i]; break; } temp = temp->next; } temp = reqlist[i]; while (temp) { numdeps++; if (temp->next == NULL) { temp->next = deplist; deplist = reqlist[i]; break; } temp = temp->next; } } if (numdeps <= 0) { fprintf(stderr, "Can't have zero requests at logorg_parity_table_dodeps_sync\n"); exit(1); } if (opid == 0) { curr->prev = NULL; curr->next = deplist; return; } depend = (depends *) getfromextraq(); depend->blkno = curr->next->blkno; depend->devno = curr->next->devno; depend->numdeps = numdeps; curr->prev = (ioreq_event *) depend; depend->deps[0] = deplist; deplist->opid = opid; temp = deplist->next; for (i=1; i<numdeps; i++) { if (devno == 0) { depend->cont = (depends *) getfromextraq(); depend = depend->cont; } depend->deps[devno] = temp; temp->opid = opid; devno = logorg_modulus_update(1, devno, 10); temp = temp->next; } temp = curr->next->next; for (i=1; i<opid; i++) { depend = (depends *) ioreq_copy(curr->prev); depend->next = (depends *) curr->prev; curr->prev = (ioreq_event *) depend; depend->blkno = temp->blkno; depend->devno = temp->devno; tmpdep = depend->cont; for (j=0; j<(numdeps/10); j++) { depend->cont = (depends *) ioreq_copy((ioreq_event *) tmpdep); tmpdep = tmpdep->cont; depend = depend->cont; } temp = temp->next; } }
static int cachedev_get_block (struct cache_if *c, ioreq_event *req, void (**donefunc)(void *, ioreq_event *), void *doneparam) { struct cache_dev *cache = (struct cache_dev *)c; struct cache_dev_event *rwdesc = (struct cache_dev_event *) getfromextraq(); ioreq_event *fillreq; int devno; #ifdef DEBUG_CACHEDEV fprintf (outputfile, "*** cachedev::totalreqs = %d\n", disksim->totalreqs); fprintf (outputfile, "*** %f: Entered cachedev::cachedev_get_block: rw %d, devno %d, blkno %d, size %d\n", simtime, (req->flags & READ), req->devno, req->blkno, req->bcount); #endif if (req->devno != cache->real_devno) { fprintf (stderr, "cachedev_get_block trying to cache blocks for wrong device (%d should be %d)\n", req->devno, cache->real_devno); ASSERT(0); exit(1); } /* Ignore request overlap and locking issues for now. */ /* Also ignore buffer space limitation issues for now. */ cache->bufferspace += req->bcount; if (cache->bufferspace > cache->stat.maxbufferspace) { cache->stat.maxbufferspace = cache->bufferspace; } rwdesc->type = (req->flags & READ) ? CACHE_EVENT_READ : CACHE_EVENT_WRITE; rwdesc->donefunc = donefunc; rwdesc->doneparam = doneparam; rwdesc->req = req; req->next = NULL; req->prev = NULL; rwdesc->flags = 0; cachedev_add_ongoing_request (cache, rwdesc); if (req->flags & READ) { cache->stat.reads++; cache->stat.readblocks += req->bcount; /* Send read straight to whichever device has it (preferably cachedev). */ if (cachedev_isreadhit (cache, req)) { devno = cache->cache_devno; cache->stat.readhitsfull++; } else { devno = cache->real_devno; cache->stat.readmisses++; } /* For now, just assume both device's store bits at same LBNs */ fillreq = ioreq_copy (req); fillreq->buf = rwdesc; fillreq->type = IO_ACCESS_ARRIVE; fillreq->devno = devno; #ifdef DEBUG_CACHEDEV fprintf (outputfile, "*** %f: cachedev::fillreq (inserts into ioqueue?): devno %d, blkno %d, bcount %d, flags %x, buf %p\n", simtime, fillreq->devno, fillreq->blkno, fillreq->bcount, fillreq->flags, fillreq->buf); #endif (*cache->issuefunc)(cache->issueparam, fillreq); return (1); } else { /* Grab buffer space and let the controller fill in data to be written. */ /* (for now, just assume that there is buffer space available) */ (*donefunc)(doneparam, req); return (0); } }
static void logorg_parity_table_dodeps_nosync (logorg *currlogorg, ioreq_event *curr, ioreq_event **redunlist, ioreq_event **reqlist) { int i; depends *depend; depends *tmpdep; ioreq_event *temp; ioreq_event *del; ioreq_event *tmpread; ioreq_event *readlist = NULL; ioreq_event *deplist = NULL; int holddep; for (i=0; i<currlogorg->actualnumdisks; i++) { temp = redunlist[i]; while (temp) { depend = (depends *) getfromextraq(); depend->blkno = temp->blkno; depend->devno = temp->devno; depend->numdeps = 0; depend->next = NULL; temp->prev = (ioreq_event *) depend; if (temp->next == NULL) { temp->next = readlist; readlist = redunlist[i]; break; } temp = temp->next; } temp = reqlist[i]; while (temp) { del = temp; temp = temp->next; if ((redunlist[i] == NULL) && (del->opid == 0)) { del->next = curr->next; curr->next = del; } else { del->next = deplist; deplist = del; } } } if (readlist == NULL) { if (deplist) { fprintf(stderr, "Unacceptable condition in logorg_parity_table_dodeps_nosync\n"); exit(1); } curr->prev = NULL; return; } temp = deplist; while (temp) { holddep = temp->opid; temp->opid = 0; tmpread = readlist; while (tmpread) { if ((tmpread->devno == temp->devno) | (holddep & tmpread->opid)) { tmpdep = (depends *) tmpread->prev; ASSERT (tmpdep != NULL); if (tmpdep->numdeps > 0) { for (i=0; i<((tmpdep->numdeps-1)/10); i++) { tmpdep = tmpdep->cont; } if ((tmpdep->numdeps % 10) == 0) { tmpdep->cont = (depends *) getfromextraq(); tmpdep = tmpdep->cont; } } tmpdep->deps[(tmpdep->numdeps % 10)] = temp; tmpdep->numdeps++; temp->opid++; } tmpread = tmpread->next; } temp = temp->next; } temp = readlist; curr->prev = NULL; while (temp) { depend = (depends *) temp->prev; temp->prev = NULL; depend->next = (depends *) curr->prev; curr->prev = (ioreq_event *) depend; if (temp->next == NULL) { temp->next = curr->next; curr->next = readlist; break; } temp = temp->next; } }
int logorg_parity_table (logorg *currlogorg, ioreq_event *curr, int numreqs) { int i; ioreq_event *reqs[MAXDEVICES]; ioreq_event *redunreqs[MAXDEVICES]; int reqcnt = 0; ioreq_event *lastrow = NULL; int stripeunit; ioreq_event *temp; ioreq_event *newreq; int unitno; int stripeno; int entryno; int blkno; int blksinpart; int reqsize; int partsperstripe; int rowcnt = 1; int firstrow = 0; int opid = 0x1; int blkscovered; tableentry *table; int tablestart; int preventryno; /* fprintf (outputfile, "Entered logorg_parity_table - devno %d, blkno %d, bcount %d, read %d\n", curr->devno, curr->blkno, curr->bcount, (curr->flags & READ)); */ if (numreqs != 1) { fprintf(stderr, "Multiple numreqs at logorg_parity_table is not acceptable - %d\n", numreqs); exit(1); } stripeunit = currlogorg->stripeunit; partsperstripe = currlogorg->partsperstripe; table = currlogorg->table; if (currlogorg->addrbyparts) { curr->blkno += curr->devno * currlogorg->blksperpart; } for (i=0; i<currlogorg->actualnumdisks; i++) { reqs[i] = NULL; } unitno = curr->blkno / stripeunit; stripeno = unitno / partsperstripe; tablestart = (stripeno / currlogorg->tablestripes) * currlogorg->tablesize; stripeno = stripeno % currlogorg->tablestripes; blkno = tablestart + table[(stripeno*(partsperstripe+1))].blkno; if (blkno == currlogorg->numfull) { stripeunit = currlogorg->actualblksperpart - blkno; curr->blkno -= blkno; unitno = curr->blkno / stripeunit; } blksinpart = stripeunit; unitno = unitno % partsperstripe; curr->blkno = curr->blkno % stripeunit; reqsize = curr->bcount; entryno = stripeno * partsperstripe + stripeno + unitno; blkno = tablestart + table[entryno].blkno; blksinpart -= curr->blkno; temp = ioreq_copy(curr); curr->next = temp; temp->blkno = blkno + curr->blkno; temp->devno = table[entryno].devno; temp->opid = 0; blkscovered = curr->bcount; curr->blkno = stripeno; curr->devno = unitno; curr->bcount = tablestart; reqs[temp->devno] = curr->next; temp->next = NULL; temp->prev = NULL; if (reqsize > blksinpart) { temp->bcount = blksinpart; blkscovered = blksinpart; reqsize -= blksinpart; unitno++; if (unitno == partsperstripe) { if (!(curr->flags & READ)) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = table[(entryno+1)].devno; newreq->blkno = table[(entryno+1)].blkno; newreq->blkno += tablestart + temp->blkno - blkno; newreq->bcount = blkscovered; newreq->flags = curr->flags; newreq->opid = 0; reqs[newreq->devno] = newreq; newreq->next = NULL; temp->prev = newreq; newreq->prev = NULL; } blkscovered = 0; unitno = 0; if (firstrow == 0) { firstrow = 1; } rowcnt = 0; stripeno++; temp = NULL; if (stripeno == currlogorg->tablestripes) { stripeno = 0; tablestart += currlogorg->tablesize; } } entryno = (stripeno * partsperstripe) + stripeno + unitno; blkno = tablestart + table[entryno].blkno; blksinpart = (blkno != currlogorg->numfull) ? stripeunit : currlogorg->actualblksperpart - blkno; while (reqsize > blksinpart) { rowcnt++; newreq = (ioreq_event *) getfromextraq(); newreq->blkno = blkno; newreq->devno = table[entryno].devno; newreq->bcount = blksinpart; blkscovered = max(blkscovered, blksinpart); newreq->flags = curr->flags; newreq->opid = 0; newreq->prev = NULL; if (temp) { temp->prev = newreq; } else { lastrow = newreq; } temp = newreq; logorg_parity_table_insert(&reqs[temp->devno], temp); reqsize -= blksinpart; unitno++; if (unitno == partsperstripe) { if (!(curr->flags & READ)) { newreq = (ioreq_event *) getfromextraq(); newreq->devno = table[(entryno+1)].devno; newreq->blkno = table[(entryno+1)].blkno + tablestart; newreq->bcount = blkscovered; newreq->flags = curr->flags; newreq->opid = 0; temp->prev = newreq; newreq->prev = NULL; logorg_parity_table_insert(&reqs[newreq->devno], newreq); } blkscovered = 0; unitno = 0; if (firstrow == 0) { firstrow = rowcnt; } rowcnt = 0; temp = NULL; stripeno++; if (stripeno == currlogorg->tablestripes) { stripeno = 0; tablestart += currlogorg->tablesize; } } entryno = (stripeno * partsperstripe) + stripeno + unitno; blkno = tablestart + table[entryno].blkno; blksinpart = (blkno != currlogorg->numfull) ? stripeunit : currlogorg->actualblksperpart - blkno; } newreq = (ioreq_event *) getfromextraq(); newreq->blkno = blkno; newreq->devno = table[entryno].devno; newreq->bcount = reqsize; rowcnt++; blkscovered = max(blkscovered, blksinpart); newreq->flags = curr->flags; newreq->opid = 0; newreq->prev = NULL; if (temp) { temp->prev = newreq; } else { lastrow = newreq; } temp = newreq; logorg_parity_table_insert(&reqs[newreq->devno], newreq); } if (curr->flags & READ) { curr->next = curr; for (i=0; i<currlogorg->actualnumdisks; i++) { reqcnt += logorg_join_seqreqs(reqs[i], curr, LOGORG_PARITY_SEQGIVE); } } else { preventryno = entryno; entryno = (stripeno * partsperstripe) + stripeno + partsperstripe; newreq = (ioreq_event *) getfromextraq(); newreq->devno = table[entryno].devno; newreq->blkno = table[entryno].blkno + temp->blkno - table[preventryno].blkno; newreq->bcount = (rowcnt == 1) ? temp->bcount : blkscovered; newreq->flags = curr->flags; newreq->opid = 0; temp->prev = newreq; newreq->prev = NULL; logorg_parity_table_insert(&reqs[newreq->devno], newreq); if (firstrow == 0) { if ((rowcnt == 2) && ((curr->next->blkno - temp->blkno - temp->bcount) > 0)) { newreq->bcount = temp->bcount; newreq = (ioreq_event *) getfromextraq(); newreq->devno = temp->prev->devno; lastrow = temp; temp = curr->next; newreq->blkno = table[entryno].blkno + temp->blkno - table[(preventryno-1)].blkno; newreq->bcount = temp->bcount; newreq->flags = curr->flags; newreq->opid = 0; temp->prev = newreq; newreq->prev = NULL; logorg_parity_table_insert(&reqs[newreq->devno], newreq); firstrow = 1; rowcnt = 1; } else { firstrow = rowcnt; rowcnt = 0; } } for (i=0; i<currlogorg->actualnumdisks; i++) { redunreqs[i] = NULL; } if (firstrow < partsperstripe) { if (firstrow < currlogorg->rmwpoint) { logorg_parity_table_read_old(currlogorg, curr->next, redunreqs, opid); } else { logorg_parity_table_recon(currlogorg, curr->next, redunreqs, curr->blkno, curr->devno, curr->bcount, opid); } opid = opid << 1; } if ((rowcnt) && (rowcnt != partsperstripe)) { if (rowcnt < currlogorg->rmwpoint) { logorg_parity_table_read_old(currlogorg, lastrow, redunreqs, opid); } else { logorg_parity_table_recon(currlogorg, lastrow, redunreqs, stripeno, 0, tablestart, opid); } } for (i=0; i<currlogorg->actualnumdisks; i++) { curr->next = NULL; reqcnt += logorg_join_seqreqs(redunreqs[i], curr, LOGORG_PARITY_SEQGIVE); redunreqs[i] = curr->next; curr->next = NULL; reqcnt += logorg_join_seqreqs(reqs[i], curr, LOGORG_PARITY_SEQGIVE); reqs[i] = curr->next; } curr->next = curr; if (currlogorg->writesync) { logorg_parity_table_dodeps_sync(currlogorg, curr, redunreqs, reqs); } else { logorg_parity_table_dodeps_nosync(currlogorg, curr, redunreqs, reqs); } } if (curr->next) { temp = curr->next; curr->blkno = temp->blkno; curr->devno = temp->devno; curr->bcount = temp->bcount; curr->flags = temp->flags; curr->next = temp->next; addtoextraq((event *) temp); } else { fprintf(stderr, "Seem to have no requests when leaving logorg_parity_table\n"); exit(1); } /* fprintf (outputfile, "Exiting logorg_parity_table - reqcnt %d\n", reqcnt); */ return(reqcnt); }
static void ssd_media_access_request_element (ioreq_event *curr) { ssd_t *currdisk = getssd(curr->devno); int blkno = curr->blkno; int count = curr->bcount; //added by tiel int i = 0; double max_threshold = currdisk->params.nelements * currdisk->params.page_size; /* **** CAREFUL ... HIJACKING tempint2 and tempptr2 fields here **** */ curr->tempint2 = count; //while (count != 0) { while (count > 0) { // find the element (package) to direct the request int elem_num = ssd_choose_element(currdisk->user_params, blkno); ssd_element *elem = &currdisk->elements[elem_num]; // create a new sub-request for the element ioreq_event *tmp = (ioreq_event *)getfromextraq(); tmp->devno = curr->devno; tmp->busno = curr->busno; tmp->flags = curr->flags; tmp->blkno = blkno; tmp->bcount = ssd_choose_aligned_count(currdisk->params.page_size, blkno, count); /*if(curr->bcount > max_threshold) tmp->tempint1 = 1;*/ //ASSERT(tmp->bcount == currdisk->params.page_size); tmp->tempptr2 = curr; blkno += tmp->bcount; count -= tmp->bcount; elem->metadata.reqs_waiting ++; // add the request to the corresponding element's queue ioqueue_add_new_request(elem->queue, (ioreq_event *)tmp); // added by tiel // activate request create simtime, type, elem_num { int ch_num; double wtime, ctime; ioreq_event *temp = (ioreq_event *)getfromextraq(); temp->type = SSD_ACTIVATE_ELEM; //Insert Channel/Way delay //Channel Number = Chip number % Number of Channel ch_num = elem_num % currdisk->params.nchannel; wtime = currdisk->CH[ch_num].arrival_time + ssd_data_transfer_cost(currdisk,currdisk->params.page_size); ctime = simtime + (i * currdisk->params.channel_switch_delay); if(currdisk->params.nchannel == currdisk->params.nelements){ temp->time = ctime; currdisk->CH[ch_num].ccount++; }else if(simtime > wtime || currdisk->CH[ch_num].flag == -1){ //channel data setting currdisk->CH[ch_num].arrival_time = ctime; currdisk->CH[ch_num].flag = curr->flags; temp->time = ctime; currdisk->CH[ch_num].ccount++; }else if(currdisk->CH[ch_num].flag ==READ){ if(wtime > ctime){ if(curr->flags == READ){ temp->time = wtime; }else{ temp->time = wtime + currdisk->params.page_read_latency; } currdisk->CH[ch_num].wcount++; }else{ temp->time = ctime; currdisk->CH[ch_num].ccount++; } currdisk->CH[ch_num].arrival_time = temp->time; currdisk->CH[ch_num].flag = curr->flags; }else if(currdisk->CH[ch_num].flag == WRITE){ if(wtime > ctime){ temp->time = wtime; currdisk->CH[ch_num].wcount++; }else{ temp->time = ctime; currdisk->CH[ch_num].ccount++; } currdisk->CH[ch_num].arrival_time = temp->time; currdisk->CH[ch_num].flag = curr->flags; } temp->ssd_elem_num = elem_num; addtointq ((event *)temp); i ++; } } }