RF_DiskQueueData_t * rf_CvscanDequeue(void *q_in) { RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in; long range, i, sum_dist_left, sum_dist_right; RF_DiskQueueData_t *ret; RF_DiskQueueData_t *tmp; DO_CHECK_STATE(hdr); if (hdr->left_cnt == 0 && hdr->right_cnt == 0) return ((RF_DiskQueueData_t *) NULL); range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt, hdr->right_cnt)); for (i = 0, tmp = hdr->left, sum_dist_left = ((hdr->direction == rf_cvscan_RIGHT) ? range * hdr->change_penalty : 0); tmp != (RF_DiskQueueData_t *) NULL && i < range; tmp = tmp->next, i++) { sum_dist_left += hdr->cur_block - tmp->sectorOffset; } for (i = 0, tmp = hdr->right, sum_dist_right = ((hdr->direction == rf_cvscan_LEFT) ? range * hdr->change_penalty : 0); tmp != (RF_DiskQueueData_t *) NULL && i < range; tmp = tmp->next, i++) { sum_dist_right += tmp->sectorOffset - hdr->cur_block; } if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) { hdr->direction = rf_cvscan_LEFT; hdr->cur_block = hdr->left->sectorOffset + hdr->left->numSector; hdr->left_cnt = RF_MAX(hdr->left_cnt - 1, 0); tmp = hdr->left; ret = (ReqDequeue(&hdr->left)) /*->parent*/ ; } else { hdr->direction = rf_cvscan_RIGHT; hdr->cur_block = hdr->right->sectorOffset + hdr->right->numSector; hdr->right_cnt = RF_MAX(hdr->right_cnt - 1, 0); tmp = hdr->right; ret = (ReqDequeue(&hdr->right)) /*->parent*/ ; } ReBalance(hdr); if (hdr->left_cnt == 0 && hdr->right_cnt == 0 && hdr->burner != (RF_DiskQueueData_t *) NULL) { /* ** restore low priority requests for next dequeue */ RF_DiskQueueData_t *burner = hdr->burner; hdr->nxt_priority = burner->priority; while (burner != (RF_DiskQueueData_t *) NULL && burner->priority == hdr->nxt_priority) { RF_DiskQueueData_t *next = burner->next; RealEnqueue(hdr, burner); burner = next; } hdr->burner = burner; } DO_CHECK_STATE(hdr); return (ret); }
RF_DiskQueueData_t * rf_CvscanPeek(void *q_in) { RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in; long range, i, sum_dist_left, sum_dist_right; RF_DiskQueueData_t *tmp, *headElement; DO_CHECK_STATE(hdr); if (hdr->left_cnt == 0 && hdr->right_cnt == 0) headElement = NULL; else { range = RF_MIN(hdr->range_for_avg, RF_MIN(hdr->left_cnt, hdr->right_cnt)); for (i = 0, tmp = hdr->left, sum_dist_left = ((hdr->direction == rf_cvscan_RIGHT) ? range * hdr->change_penalty : 0); tmp != (RF_DiskQueueData_t *) NULL && i < range; tmp = tmp->next, i++) { sum_dist_left += hdr->cur_block - tmp->sectorOffset; } for (i = 0, tmp = hdr->right, sum_dist_right = ((hdr->direction == rf_cvscan_LEFT) ? range * hdr->change_penalty : 0); tmp != (RF_DiskQueueData_t *) NULL && i < range; tmp = tmp->next, i++) { sum_dist_right += tmp->sectorOffset - hdr->cur_block; } if (hdr->right_cnt == 0 || sum_dist_left < sum_dist_right) headElement = hdr->left; else headElement = hdr->right; } return (headElement); }
/* * Promote reconstruction accesses for the given stripeID to normal priority. * Return 1 if an access was found and zero otherwise. * Normally, we should only have one or zero entries in the burner queue, * so execution time should be short. */ int rf_CvscanPromote(void *q_in, RF_StripeNum_t parityStripeID, RF_ReconUnitNum_t which_ru) { RF_CvscanHeader_t *hdr = (RF_CvscanHeader_t *) q_in; RF_DiskQueueData_t *trailer = NULL, *tmp = hdr->burner, *tlist = NULL; int retval = 0; DO_CHECK_STATE(hdr); while (tmp) { /* Handle entries at the front of the list. */ if (tmp->parityStripeID == parityStripeID && tmp->which_ru == which_ru) { hdr->burner = tmp->next; tmp->priority = RF_IO_NORMAL_PRIORITY; tmp->next = tlist; tlist = tmp; tmp = hdr->burner; } else break; } if (tmp) { trailer = tmp; tmp = tmp->next; } while (tmp) { /* Handle entries on the rest of the list. */ if (tmp->parityStripeID == parityStripeID && tmp->which_ru == which_ru) { trailer->next = tmp->next; tmp->priority = RF_IO_NORMAL_PRIORITY; tmp->next = tlist; tlist = tmp; /* Insert on a temp queue. */ tmp = trailer->next; } else { trailer = tmp; tmp = tmp->next; } } while (tlist) { retval++; tmp = tlist->next; rf_RealEnqueue(hdr, tlist); tlist = tmp; } RF_ASSERT(retval == 0 || retval == 1); DO_CHECK_STATE((RF_CvscanHeader_t *) q_in); return (retval); }
void rf_RealEnqueue(RF_CvscanHeader_t *hdr, RF_DiskQueueData_t *req) { RF_ASSERT(req->priority == RF_IO_NORMAL_PRIORITY || req->priority == RF_IO_LOW_PRIORITY); DO_CHECK_STATE(hdr); if (hdr->left_cnt == 0 && hdr->right_cnt == 0) { hdr->nxt_priority = req->priority; } if (req->priority > hdr->nxt_priority) { /* * Dump all other outstanding requests on the back burner. */ rf_Transfer(&hdr->burner, &hdr->left); rf_Transfer(&hdr->burner, &hdr->right); hdr->left_cnt = 0; hdr->right_cnt = 0; hdr->nxt_priority = req->priority; } if (req->priority < hdr->nxt_priority) { /* * Yet another low priority task ! */ rf_PriorityInsert(&hdr->burner, req); } else { if (req->sectorOffset < hdr->cur_block) { /* This request is to the left of the current arms. */ rf_ReqInsert(&hdr->left, req, rf_cvscan_LEFT); hdr->left_cnt++; } else { /* This request is to the right of the current arms. */ rf_ReqInsert(&hdr->right, req, rf_cvscan_RIGHT); hdr->right_cnt++; } } DO_CHECK_STATE(hdr); }
void * rf_CvscanCreate(RF_SectorCount_t sectPerDisk, RF_AllocListElem_t * clList, RF_ShutdownList_t ** listp) { RF_CvscanHeader_t *hdr; long range = 2; /* Currently no mechanism to change these */ long penalty = sectPerDisk / 5; RF_MallocAndAdd(hdr, sizeof(RF_CvscanHeader_t), (RF_CvscanHeader_t *), clList); bzero((char *) hdr, sizeof(RF_CvscanHeader_t)); hdr->range_for_avg = RF_MAX(range, 1); hdr->change_penalty = RF_MAX(penalty, 0); hdr->direction = rf_cvscan_RIGHT; hdr->cur_block = 0; hdr->left_cnt = hdr->right_cnt = 0; hdr->left = hdr->right = (RF_DiskQueueData_t *) NULL; hdr->burner = (RF_DiskQueueData_t *) NULL; DO_CHECK_STATE(hdr); return ((void *) hdr); }