예제 #1
0
/*
 * The following three states create, execute, and post-process DAGs.
 * The error recovery unit is a single DAG.
 * By default, SelectAlgorithm creates an array of DAGs, one per parity stripe.
 * In some tricky cases, multiple dags per stripe are created.
 *   - DAGs within a parity stripe are executed sequentially (arbitrary order).
 *   - DAGs for distinct parity stripes are executed concurrently.
 *
 * Repeat until all DAGs complete successfully -or- DAG selection fails.
 *
 * while !done
 *   create dag(s) (SelectAlgorithm)
 *   if dag
 *     execute dag (DispatchDAG)
 *     if dag successful
 *       done (SUCCESS)
 *     else
 *       !done (RETRY - start over with new dags)
 *   else
 *     done (FAIL)
 */
int
rf_State_CreateDAG(RF_RaidAccessDesc_t *desc)
{
	RF_AccTraceEntry_t *tracerec = &desc->tracerec;
	RF_Etimer_t timer;
	RF_DagHeader_t *dag_h;
	int i, selectStatus;

	/*
	 * Generate a dag for the access, and fire it off. When the dag
	 * completes, we'll get re-invoked in the next state.
	 */
	RF_ETIMER_START(timer);
	/* SelectAlgorithm returns one or more dags. */
	selectStatus = rf_SelectAlgorithm(desc,
	    desc->flags | RF_DAG_SUPPRESS_LOCKS);
	if (rf_printDAGsDebug)
		for (i = 0; i < desc->numStripes; i++)
			rf_PrintDAGList(desc->dagArray[i].dags);
	RF_ETIMER_STOP(timer);
	RF_ETIMER_EVAL(timer);
	/* Update time to create all dags. */
	tracerec->specific.user.dag_create_us = RF_ETIMER_VAL_US(timer);

	desc->status = 0;	/* Good status. */

	if (selectStatus) {
		/* Failed to create a dag. */
		/*
		 * This happens when there are too many faults or incomplete
		 * dag libraries.
		 */
		printf("[Failed to create a DAG]\n");
		RF_PANIC();
	} else {
		/* Bind dags to desc. */
		for (i = 0; i < desc->numStripes; i++) {
			dag_h = desc->dagArray[i].dags;
			while (dag_h) {
				dag_h->bp = (struct buf *) desc->bp;
				dag_h->tracerec = tracerec;
				dag_h = dag_h->next;
			}
		}
		desc->flags |= RF_DAG_DISPATCH_RETURNED;
		desc->state++;	/* Next state should be rf_State_ExecuteDAG. */
	}
	return RF_FALSE;
}
예제 #2
0
/*
 * the following three states create, execute, and post-process dags
 * the error recovery unit is a single dag.
 * by default, SelectAlgorithm creates an array of dags, one per parity stripe
 * in some tricky cases, multiple dags per stripe are created
 *   - dags within a parity stripe are executed sequentially (arbitrary order)
 *   - dags for distinct parity stripes are executed concurrently
 *
 * repeat until all dags complete successfully -or- dag selection fails
 *
 * while !done
 *   create dag(s) (SelectAlgorithm)
 *   if dag
 *     execute dag (DispatchDAG)
 *     if dag successful
 *       done (SUCCESS)
 *     else
 *       !done (RETRY - start over with new dags)
 *   else
 *     done (FAIL)
 */
int
rf_State_CreateDAG(RF_RaidAccessDesc_t *desc)
{
#if RF_ACC_TRACE > 0
	RF_AccTraceEntry_t *tracerec = &desc->tracerec;
	RF_Etimer_t timer;
#endif
	RF_DagHeader_t *dag_h;
	RF_DagList_t *dagList;
	struct buf *bp;
	int     i, selectStatus;

	/* generate a dag for the access, and fire it off.  When the dag
	 * completes, we'll get re-invoked in the next state. */
#if RF_ACC_TRACE > 0
	RF_ETIMER_START(timer);
#endif
	/* SelectAlgorithm returns one or more dags */
	selectStatus = rf_SelectAlgorithm(desc, desc->flags | RF_DAG_SUPPRESS_LOCKS);
#if RF_DEBUG_VALIDATE_DAG
	if (rf_printDAGsDebug) {
		dagList = desc->dagList;
		for (i = 0; i < desc->numStripes; i++) {
			rf_PrintDAGList(dagList->dags);
			dagList = dagList->next;
		}
	}
#endif /* RF_DEBUG_VALIDATE_DAG */
#if RF_ACC_TRACE > 0
	RF_ETIMER_STOP(timer);
	RF_ETIMER_EVAL(timer);
	/* update time to create all dags */
	tracerec->specific.user.dag_create_us = RF_ETIMER_VAL_US(timer);
#endif

	desc->status = 0;	/* good status */

	if (selectStatus || (desc->numRetries > RF_RETRY_THRESHOLD)) {
		/* failed to create a dag */
		/* this happens when there are too many faults or incomplete
		 * dag libraries */
		if (selectStatus) {
			printf("raid%d: failed to create a dag. "
			       "Too many component failures.\n",
			       desc->raidPtr->raidid);
		} else {
			printf("raid%d: IO failed after %d retries.\n",
			       desc->raidPtr->raidid, RF_RETRY_THRESHOLD);
		}

		desc->status = 1; /* bad status */
		/* skip straight to rf_State_Cleanup() */
		desc->state = rf_CleanupState;
		bp = (struct buf *)desc->bp;
		bp->b_error = EIO;
		bp->b_resid = bp->b_bcount;
	} else {
		/* bind dags to desc */
		dagList = desc->dagList;
		for (i = 0; i < desc->numStripes; i++) {
			dag_h = dagList->dags;
			while (dag_h) {
				dag_h->bp = (struct buf *) desc->bp;
#if RF_ACC_TRACE > 0
				dag_h->tracerec = tracerec;
#endif
				dag_h = dag_h->next;
			}
			dagList = dagList->next;
		}
		desc->flags |= RF_DAG_DISPATCH_RETURNED;
		desc->state++;	/* next state should be rf_State_ExecuteDAG */
	}
	return RF_FALSE;
}