Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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);
}