/* * 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; }
/* * 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; }