[BACK]Return to rf_states.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

Annotation of sys/dev/raidframe/rf_states.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: rf_states.c,v 1.9 2002/12/16 07:01:05 tdeval Exp $    */
        !             2: /*     $NetBSD: rf_states.c,v 1.15 2000/10/20 02:24:45 oster Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Mark Holland, William V. Courtright II, Robby Findler
        !             9:  *
        !            10:  * Permission to use, copy, modify and distribute this software and
        !            11:  * its documentation is hereby granted, provided that both the copyright
        !            12:  * notice and this permission notice appear in all copies of the
        !            13:  * software, derivative works or modified versions, and any portions
        !            14:  * thereof, and that both notices appear in supporting documentation.
        !            15:  *
        !            16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            19:  *
        !            20:  * Carnegie Mellon requests users of this software to return to
        !            21:  *
        !            22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            23:  *  School of Computer Science
        !            24:  *  Carnegie Mellon University
        !            25:  *  Pittsburgh PA 15213-3890
        !            26:  *
        !            27:  * any improvements or extensions that they make and grant Carnegie the
        !            28:  * rights to redistribute these changes.
        !            29:  */
        !            30:
        !            31: #include <sys/errno.h>
        !            32:
        !            33: #include "rf_archs.h"
        !            34: #include "rf_threadstuff.h"
        !            35: #include "rf_raid.h"
        !            36: #include "rf_dag.h"
        !            37: #include "rf_desc.h"
        !            38: #include "rf_aselect.h"
        !            39: #include "rf_general.h"
        !            40: #include "rf_states.h"
        !            41: #include "rf_dagutils.h"
        !            42: #include "rf_driver.h"
        !            43: #include "rf_engine.h"
        !            44: #include "rf_map.h"
        !            45: #include "rf_etimer.h"
        !            46: #include "rf_kintf.h"
        !            47:
        !            48: /*
        !            49:  * Prototypes for some of the available states.
        !            50:  *
        !            51:  * States must:
        !            52:  *
        !            53:  *   - not block.
        !            54:  *
        !            55:  *   - either schedule rf_ContinueRaidAccess as a callback and return
        !            56:  *     RF_TRUE, or complete all of their work and return RF_FALSE.
        !            57:  *
        !            58:  *   - increment desc->state when they have finished their work.
        !            59:  */
        !            60:
        !            61: char *StateName(RF_AccessState_t);
        !            62:
        !            63: char *
        !            64: StateName(RF_AccessState_t state)
        !            65: {
        !            66:        switch (state) {
        !            67:                case rf_QuiesceState:return "QuiesceState";
        !            68:        case rf_MapState:
        !            69:                return "MapState";
        !            70:        case rf_LockState:
        !            71:                return "LockState";
        !            72:        case rf_CreateDAGState:
        !            73:                return "CreateDAGState";
        !            74:        case rf_ExecuteDAGState:
        !            75:                return "ExecuteDAGState";
        !            76:        case rf_ProcessDAGState:
        !            77:                return "ProcessDAGState";
        !            78:        case rf_CleanupState:
        !            79:                return "CleanupState";
        !            80:        case rf_LastState:
        !            81:                return "LastState";
        !            82:        case rf_IncrAccessesCountState:
        !            83:                return "IncrAccessesCountState";
        !            84:        case rf_DecrAccessesCountState:
        !            85:                return "DecrAccessesCountState";
        !            86:        default:
        !            87:                return "!!! UnnamedState !!!";
        !            88:        }
        !            89: }
        !            90:
        !            91: void
        !            92: rf_ContinueRaidAccess(RF_RaidAccessDesc_t *desc)
        !            93: {
        !            94:        int suspended = RF_FALSE;
        !            95:        int current_state_index = desc->state;
        !            96:        RF_AccessState_t current_state = desc->states[current_state_index];
        !            97:        int unit = desc->raidPtr->raidid;
        !            98:
        !            99:        do {
        !           100:                current_state_index = desc->state;
        !           101:                current_state = desc->states[current_state_index];
        !           102:
        !           103:                switch (current_state) {
        !           104:
        !           105:                case rf_QuiesceState:
        !           106:                        suspended = rf_State_Quiesce(desc);
        !           107:                        break;
        !           108:                case rf_IncrAccessesCountState:
        !           109:                        suspended = rf_State_IncrAccessCount(desc);
        !           110:                        break;
        !           111:                case rf_MapState:
        !           112:                        suspended = rf_State_Map(desc);
        !           113:                        break;
        !           114:                case rf_LockState:
        !           115:                        suspended = rf_State_Lock(desc);
        !           116:                        break;
        !           117:                case rf_CreateDAGState:
        !           118:                        suspended = rf_State_CreateDAG(desc);
        !           119:                        break;
        !           120:                case rf_ExecuteDAGState:
        !           121:                        suspended = rf_State_ExecuteDAG(desc);
        !           122:                        break;
        !           123:                case rf_ProcessDAGState:
        !           124:                        suspended = rf_State_ProcessDAG(desc);
        !           125:                        break;
        !           126:                case rf_CleanupState:
        !           127:                        suspended = rf_State_Cleanup(desc);
        !           128:                        break;
        !           129:                case rf_DecrAccessesCountState:
        !           130:                        suspended = rf_State_DecrAccessCount(desc);
        !           131:                        break;
        !           132:                case rf_LastState:
        !           133:                        suspended = rf_State_LastState(desc);
        !           134:                        break;
        !           135:                }
        !           136:
        !           137:                /*
        !           138:                 * After this point, we cannot dereference desc since desc may
        !           139:                 * have been freed. desc is only freed in LastState, so if we
        !           140:                 * reenter this function or loop back up, desc should be valid.
        !           141:                 */
        !           142:
        !           143:                if (rf_printStatesDebug) {
        !           144:                        printf("raid%d: State: %-24s StateIndex: %3i desc:"
        !           145:                               " 0x%ld %s.\n", unit, StateName(current_state),
        !           146:                               current_state_index, (long) desc, suspended ?
        !           147:                               "callback scheduled" : "looping");
        !           148:                }
        !           149:        } while (!suspended && current_state != rf_LastState);
        !           150:
        !           151:        return;
        !           152: }
        !           153:
        !           154:
        !           155: void
        !           156: rf_ContinueDagAccess(RF_DagList_t *dagList)
        !           157: {
        !           158:        RF_AccTraceEntry_t *tracerec = &(dagList->desc->tracerec);
        !           159:        RF_RaidAccessDesc_t *desc;
        !           160:        RF_DagHeader_t *dag_h;
        !           161:        RF_Etimer_t timer;
        !           162:        int i;
        !           163:
        !           164:        desc = dagList->desc;
        !           165:
        !           166:        timer = tracerec->timer;
        !           167:        RF_ETIMER_STOP(timer);
        !           168:        RF_ETIMER_EVAL(timer);
        !           169:        tracerec->specific.user.exec_us = RF_ETIMER_VAL_US(timer);
        !           170:        RF_ETIMER_START(tracerec->timer);
        !           171:
        !           172:        /* Skip to dag which just finished. */
        !           173:        dag_h = dagList->dags;
        !           174:        for (i = 0; i < dagList->numDagsDone; i++) {
        !           175:                dag_h = dag_h->next;
        !           176:        }
        !           177:
        !           178:        /* Check to see if retry is required. */
        !           179:        if (dag_h->status == rf_rollBackward) {
        !           180:                /*
        !           181:                 * When a dag fails, mark desc status as bad and allow all
        !           182:                 * other dags in the desc to execute to completion. Then,
        !           183:                 * free all dags and start over.
        !           184:                 */
        !           185:                desc->status = 1;       /* Bad status. */
        !           186:                {
        !           187:                        printf("raid%d: DAG failure: %c addr 0x%lx (%ld)"
        !           188:                               " nblk 0x%x (%d) buf 0x%lx.\n",
        !           189:                               desc->raidPtr->raidid, desc->type,
        !           190:                               (long) desc->raidAddress,
        !           191:                               (long) desc->raidAddress,
        !           192:                               (int) desc->numBlocks, (int) desc->numBlocks,
        !           193:                               (unsigned long) (desc->bufPtr));
        !           194:                }
        !           195:        }
        !           196:        dagList->numDagsDone++;
        !           197:        rf_ContinueRaidAccess(desc);
        !           198: }
        !           199:
        !           200: int
        !           201: rf_State_LastState(RF_RaidAccessDesc_t *desc)
        !           202: {
        !           203:        void (*callbackFunc) (RF_CBParam_t) = desc->callbackFunc;
        !           204:        RF_CBParam_t callbackArg;
        !           205:
        !           206:        callbackArg.p = desc->callbackArg;
        !           207:
        !           208:        /*
        !           209:         * If this is not an async request, wake up the caller.
        !           210:         */
        !           211:        if (desc->async_flag == 0)
        !           212:                wakeup(desc->bp);
        !           213:
        !           214:        /*
        !           215:         * That's all the IO for this one... Unbusy the 'disk'.
        !           216:         */
        !           217:
        !           218:        rf_disk_unbusy(desc);
        !           219:
        !           220:        /*
        !           221:         * Wakeup any requests waiting to go.
        !           222:         */
        !           223:
        !           224:        RF_LOCK_MUTEX(((RF_Raid_t *) desc->raidPtr)->mutex);
        !           225:        ((RF_Raid_t *) desc->raidPtr)->openings++;
        !           226:        RF_UNLOCK_MUTEX(((RF_Raid_t *) desc->raidPtr)->mutex);
        !           227:
        !           228:        /* Wake up any pending I/O. */
        !           229:        raidstart(((RF_Raid_t *) desc->raidPtr));
        !           230:
        !           231:        /* printf("%s: Calling biodone on 0x%x.\n", __func__, desc->bp); */
        !           232:        splassert(IPL_BIO);
        !           233:        biodone(desc->bp);      /* Access came through ioctl. */
        !           234:
        !           235:        if (callbackFunc)
        !           236:                callbackFunc(callbackArg);
        !           237:        rf_FreeRaidAccDesc(desc);
        !           238:
        !           239:        return RF_FALSE;
        !           240: }
        !           241:
        !           242: int
        !           243: rf_State_IncrAccessCount(RF_RaidAccessDesc_t *desc)
        !           244: {
        !           245:        RF_Raid_t *raidPtr;
        !           246:
        !           247:        raidPtr = desc->raidPtr;
        !           248:        /*
        !           249:         * Bummer. We have to do this to be 100% safe w.r.t. the increment
        !           250:         * below.
        !           251:         */
        !           252:        RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           253:        raidPtr->accs_in_flight++;      /* Used to detect quiescence. */
        !           254:        RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           255:
        !           256:        desc->state++;
        !           257:        return RF_FALSE;
        !           258: }
        !           259:
        !           260: int
        !           261: rf_State_DecrAccessCount(RF_RaidAccessDesc_t *desc)
        !           262: {
        !           263:        RF_Raid_t *raidPtr;
        !           264:
        !           265:        raidPtr = desc->raidPtr;
        !           266:
        !           267:        RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           268:        raidPtr->accs_in_flight--;
        !           269:        if (raidPtr->accesses_suspended && raidPtr->accs_in_flight == 0) {
        !           270:                rf_SignalQuiescenceLock(raidPtr, raidPtr->reconDesc);
        !           271:        }
        !           272:        rf_UpdateUserStats(raidPtr, RF_ETIMER_VAL_US(desc->timer),
        !           273:            desc->numBlocks);
        !           274:        RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           275:
        !           276:        desc->state++;
        !           277:        return RF_FALSE;
        !           278: }
        !           279:
        !           280: int
        !           281: rf_State_Quiesce(RF_RaidAccessDesc_t *desc)
        !           282: {
        !           283:        RF_AccTraceEntry_t *tracerec = &desc->tracerec;
        !           284:        RF_Etimer_t timer;
        !           285:        int suspended = RF_FALSE;
        !           286:        RF_Raid_t *raidPtr;
        !           287:
        !           288:        raidPtr = desc->raidPtr;
        !           289:
        !           290:        RF_ETIMER_START(timer);
        !           291:        RF_ETIMER_START(desc->timer);
        !           292:
        !           293:        RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           294:        if (raidPtr->accesses_suspended) {
        !           295:                RF_CallbackDesc_t *cb;
        !           296:                cb = rf_AllocCallbackDesc();
        !           297:                /*
        !           298:                 * XXX The following cast is quite bogus...
        !           299:                 * rf_ContinueRaidAccess takes a (RF_RaidAccessDesc_t *)
        !           300:                 * as an argument... GO
        !           301:                 */
        !           302:                cb->callbackFunc = (void (*) (RF_CBParam_t))
        !           303:                    rf_ContinueRaidAccess;
        !           304:                cb->callbackArg.p = (void *) desc;
        !           305:                cb->next = raidPtr->quiesce_wait_list;
        !           306:                raidPtr->quiesce_wait_list = cb;
        !           307:                suspended = RF_TRUE;
        !           308:        }
        !           309:        RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
        !           310:
        !           311:        RF_ETIMER_STOP(timer);
        !           312:        RF_ETIMER_EVAL(timer);
        !           313:        tracerec->specific.user.suspend_ovhd_us += RF_ETIMER_VAL_US(timer);
        !           314:
        !           315:        if (suspended && rf_quiesceDebug)
        !           316:                printf("Stalling access due to quiescence lock.\n");
        !           317:
        !           318:        desc->state++;
        !           319:        return suspended;
        !           320: }
        !           321:
        !           322: int
        !           323: rf_State_Map(RF_RaidAccessDesc_t *desc)
        !           324: {
        !           325:        RF_Raid_t *raidPtr = desc->raidPtr;
        !           326:        RF_AccTraceEntry_t *tracerec = &desc->tracerec;
        !           327:        RF_Etimer_t timer;
        !           328:
        !           329:        RF_ETIMER_START(timer);
        !           330:
        !           331:        if (!(desc->asmap = rf_MapAccess(raidPtr, desc->raidAddress,
        !           332:             desc->numBlocks, desc->bufPtr, RF_DONT_REMAP)))
        !           333:                RF_PANIC();
        !           334:
        !           335:        RF_ETIMER_STOP(timer);
        !           336:        RF_ETIMER_EVAL(timer);
        !           337:        tracerec->specific.user.map_us = RF_ETIMER_VAL_US(timer);
        !           338:
        !           339:        desc->state++;
        !           340:        return RF_FALSE;
        !           341: }
        !           342:
        !           343: int
        !           344: rf_State_Lock(RF_RaidAccessDesc_t *desc)
        !           345: {
        !           346:        RF_AccTraceEntry_t *tracerec = &desc->tracerec;
        !           347:        RF_Raid_t *raidPtr = desc->raidPtr;
        !           348:        RF_AccessStripeMapHeader_t *asmh = desc->asmap;
        !           349:        RF_AccessStripeMap_t *asm_p;
        !           350:        RF_Etimer_t timer;
        !           351:        int suspended = RF_FALSE;
        !           352:
        !           353:        RF_ETIMER_START(timer);
        !           354:        if (!(raidPtr->Layout.map->flags & RF_NO_STRIPE_LOCKS)) {
        !           355:                RF_StripeNum_t lastStripeID = -1;
        !           356:
        !           357:                /* Acquire each lock that we don't already hold. */
        !           358:                for (asm_p = asmh->stripeMap; asm_p; asm_p = asm_p->next) {
        !           359:                        RF_ASSERT(RF_IO_IS_R_OR_W(desc->type));
        !           360:                        if (!rf_suppressLocksAndLargeWrites &&
        !           361:                            asm_p->parityInfo &&
        !           362:                            !(desc->flags & RF_DAG_SUPPRESS_LOCKS) &&
        !           363:                            !(asm_p->flags & RF_ASM_FLAGS_LOCK_TRIED)) {
        !           364:                                asm_p->flags |= RF_ASM_FLAGS_LOCK_TRIED;
        !           365:                                /* Locks must be acquired hierarchically. */
        !           366:                                RF_ASSERT(asm_p->stripeID > lastStripeID);
        !           367:                                lastStripeID = asm_p->stripeID;
        !           368:                                /*
        !           369:                                 * XXX The cast to (void (*)(RF_CBParam_t))
        !           370:                                 * below is bogus !  GO
        !           371:                                 */
        !           372:                                RF_INIT_LOCK_REQ_DESC(asm_p->lockReqDesc,
        !           373:                                    desc->type, (void (*) (struct buf *))
        !           374:                                     rf_ContinueRaidAccess, desc, asm_p,
        !           375:                                    raidPtr->Layout.dataSectorsPerStripe);
        !           376:                                if (rf_AcquireStripeLock(raidPtr->lockTable,
        !           377:                                     asm_p->stripeID, &asm_p->lockReqDesc)) {
        !           378:                                        suspended = RF_TRUE;
        !           379:                                        break;
        !           380:                                }
        !           381:                        }
        !           382:                        if (desc->type == RF_IO_TYPE_WRITE &&
        !           383:                            raidPtr->status[asm_p->physInfo->row] ==
        !           384:                            rf_rs_reconstructing) {
        !           385:                                if (!(asm_p->flags & RF_ASM_FLAGS_FORCE_TRIED))
        !           386:                                {
        !           387:                                        int val;
        !           388:
        !           389:                                        asm_p->flags |=
        !           390:                                            RF_ASM_FLAGS_FORCE_TRIED;
        !           391:                                        /*
        !           392:                                         * XXX The cast below is quite
        !           393:                                         * bogus !!! XXX  GO
        !           394:                                         */
        !           395:                                        val = rf_ForceOrBlockRecon(raidPtr,
        !           396:                                            asm_p,
        !           397:                                            (void (*) (RF_Raid_t *, void *))
        !           398:                                             rf_ContinueRaidAccess, desc);
        !           399:                                        if (val == 0) {
        !           400:                                                asm_p->flags |=
        !           401:                                                    RF_ASM_FLAGS_RECON_BLOCKED;
        !           402:                                        } else {
        !           403:                                                suspended = RF_TRUE;
        !           404:                                                break;
        !           405:                                        }
        !           406:                                } else {
        !           407:                                        if (rf_pssDebug) {
        !           408:                                                printf("raid%d: skipping"
        !           409:                                                       " force/block because"
        !           410:                                                       " already done, psid"
        !           411:                                                       " %ld.\n",
        !           412:                                                       desc->raidPtr->raidid,
        !           413:                                                       (long) asm_p->stripeID);
        !           414:                                        }
        !           415:                                }
        !           416:                        } else {
        !           417:                                if (rf_pssDebug) {
        !           418:                                        printf("raid%d: skipping force/block"
        !           419:                                               " because not write or not"
        !           420:                                               " under recon, psid %ld.\n",
        !           421:                                               desc->raidPtr->raidid,
        !           422:                                               (long) asm_p->stripeID);
        !           423:                                }
        !           424:                        }
        !           425:                }
        !           426:
        !           427:                RF_ETIMER_STOP(timer);
        !           428:                RF_ETIMER_EVAL(timer);
        !           429:                tracerec->specific.user.lock_us += RF_ETIMER_VAL_US(timer);
        !           430:
        !           431:                if (suspended)
        !           432:                        return (RF_TRUE);
        !           433:        }
        !           434:        desc->state++;
        !           435:        return (RF_FALSE);
        !           436: }
        !           437:
        !           438: /*
        !           439:  * The following three states create, execute, and post-process DAGs.
        !           440:  * The error recovery unit is a single DAG.
        !           441:  * By default, SelectAlgorithm creates an array of DAGs, one per parity stripe.
        !           442:  * In some tricky cases, multiple dags per stripe are created.
        !           443:  *   - DAGs within a parity stripe are executed sequentially (arbitrary order).
        !           444:  *   - DAGs for distinct parity stripes are executed concurrently.
        !           445:  *
        !           446:  * Repeat until all DAGs complete successfully -or- DAG selection fails.
        !           447:  *
        !           448:  * while !done
        !           449:  *   create dag(s) (SelectAlgorithm)
        !           450:  *   if dag
        !           451:  *     execute dag (DispatchDAG)
        !           452:  *     if dag successful
        !           453:  *       done (SUCCESS)
        !           454:  *     else
        !           455:  *       !done (RETRY - start over with new dags)
        !           456:  *   else
        !           457:  *     done (FAIL)
        !           458:  */
        !           459: int
        !           460: rf_State_CreateDAG(RF_RaidAccessDesc_t *desc)
        !           461: {
        !           462:        RF_AccTraceEntry_t *tracerec = &desc->tracerec;
        !           463:        RF_Etimer_t timer;
        !           464:        RF_DagHeader_t *dag_h;
        !           465:        int i, selectStatus;
        !           466:
        !           467:        /*
        !           468:         * Generate a dag for the access, and fire it off. When the dag
        !           469:         * completes, we'll get re-invoked in the next state.
        !           470:         */
        !           471:        RF_ETIMER_START(timer);
        !           472:        /* SelectAlgorithm returns one or more dags. */
        !           473:        selectStatus = rf_SelectAlgorithm(desc,
        !           474:            desc->flags | RF_DAG_SUPPRESS_LOCKS);
        !           475:        if (rf_printDAGsDebug)
        !           476:                for (i = 0; i < desc->numStripes; i++)
        !           477:                        rf_PrintDAGList(desc->dagArray[i].dags);
        !           478:        RF_ETIMER_STOP(timer);
        !           479:        RF_ETIMER_EVAL(timer);
        !           480:        /* Update time to create all dags. */
        !           481:        tracerec->specific.user.dag_create_us = RF_ETIMER_VAL_US(timer);
        !           482:
        !           483:        desc->status = 0;       /* Good status. */
        !           484:
        !           485:        if (selectStatus) {
        !           486:                /* Failed to create a dag. */
        !           487:                /*
        !           488:                 * This happens when there are too many faults or incomplete
        !           489:                 * dag libraries.
        !           490:                 */
        !           491:                printf("[Failed to create a DAG]\n");
        !           492:                RF_PANIC();
        !           493:        } else {
        !           494:                /* Bind dags to desc. */
        !           495:                for (i = 0; i < desc->numStripes; i++) {
        !           496:                        dag_h = desc->dagArray[i].dags;
        !           497:                        while (dag_h) {
        !           498:                                dag_h->bp = (struct buf *) desc->bp;
        !           499:                                dag_h->tracerec = tracerec;
        !           500:                                dag_h = dag_h->next;
        !           501:                        }
        !           502:                }
        !           503:                desc->flags |= RF_DAG_DISPATCH_RETURNED;
        !           504:                desc->state++;  /* Next state should be rf_State_ExecuteDAG. */
        !           505:        }
        !           506:        return RF_FALSE;
        !           507: }
        !           508:
        !           509:
        !           510: /*
        !           511:  * The access has an array of dagLists, one dagList per parity stripe.
        !           512:  * Fire the first DAG in each parity stripe (dagList).
        !           513:  * DAGs within a stripe (dagList) must be executed sequentially.
        !           514:  *  - This preserves atomic parity update.
        !           515:  * DAGs for independents parity groups (stripes) are fired concurrently.
        !           516:  */
        !           517: int
        !           518: rf_State_ExecuteDAG(RF_RaidAccessDesc_t *desc)
        !           519: {
        !           520:        int i;
        !           521:        RF_DagHeader_t *dag_h;
        !           522:        RF_DagList_t *dagArray = desc->dagArray;
        !           523:
        !           524:        /*
        !           525:         * Next state is always rf_State_ProcessDAG. Important to do this
        !           526:         * before firing the first dag (it may finish before we leave this
        !           527:         * routine).
        !           528:         */
        !           529:        desc->state++;
        !           530:
        !           531:        /*
        !           532:         * Sweep dag array, a stripe at a time, firing the first dag in each
        !           533:         * stripe.
        !           534:         */
        !           535:        for (i = 0; i < desc->numStripes; i++) {
        !           536:                RF_ASSERT(dagArray[i].numDags > 0);
        !           537:                RF_ASSERT(dagArray[i].numDagsDone == 0);
        !           538:                RF_ASSERT(dagArray[i].numDagsFired == 0);
        !           539:                RF_ETIMER_START(dagArray[i].tracerec.timer);
        !           540:                /* Fire first dag in this stripe. */
        !           541:                dag_h = dagArray[i].dags;
        !           542:                RF_ASSERT(dag_h);
        !           543:                dagArray[i].numDagsFired++;
        !           544:                /*
        !           545:                 * XXX Yet another case where we pass in a conflicting
        !           546:                 * function pointer :-(  XXX  GO
        !           547:                 */
        !           548:                rf_DispatchDAG(dag_h, (void (*) (void *)) rf_ContinueDagAccess,
        !           549:                    &dagArray[i]);
        !           550:        }
        !           551:
        !           552:        /*
        !           553:         * The DAG will always call the callback, even if there was no
        !           554:         * blocking, so we are always suspended in this state.
        !           555:         */
        !           556:        return RF_TRUE;
        !           557: }
        !           558:
        !           559:
        !           560: /*
        !           561:  * rf_State_ProcessDAG is entered when a dag completes.
        !           562:  * First, check that all DAGs in the access have completed.
        !           563:  * If not, fire as many DAGs as possible.
        !           564:  */
        !           565: int
        !           566: rf_State_ProcessDAG(RF_RaidAccessDesc_t *desc)
        !           567: {
        !           568:        RF_AccessStripeMapHeader_t *asmh = desc->asmap;
        !           569:        RF_Raid_t *raidPtr = desc->raidPtr;
        !           570:        RF_DagHeader_t *dag_h;
        !           571:        int i, j, done = RF_TRUE;
        !           572:        RF_DagList_t *dagArray = desc->dagArray;
        !           573:        RF_Etimer_t timer;
        !           574:
        !           575:        /* Check to see if this is the last dag. */
        !           576:        for (i = 0; i < desc->numStripes; i++)
        !           577:                if (dagArray[i].numDags != dagArray[i].numDagsDone)
        !           578:                        done = RF_FALSE;
        !           579:
        !           580:        if (done) {
        !           581:                if (desc->status) {
        !           582:                        /* A dag failed, retry. */
        !           583:                        RF_ETIMER_START(timer);
        !           584:                        /* Free all dags. */
        !           585:                        for (i = 0; i < desc->numStripes; i++) {
        !           586:                                rf_FreeDAG(desc->dagArray[i].dags);
        !           587:                        }
        !           588:                        rf_MarkFailuresInASMList(raidPtr, asmh);
        !           589:                        /* Back up to rf_State_CreateDAG. */
        !           590:                        desc->state = desc->state - 2;
        !           591:                        return RF_FALSE;
        !           592:                } else {
        !           593:                        /* Move on to rf_State_Cleanup. */
        !           594:                        desc->state++;
        !           595:                }
        !           596:                return RF_FALSE;
        !           597:        } else {
        !           598:                /* More dags to execute. */
        !           599:                /* See if any are ready to be fired. If so, fire them. */
        !           600:                /*
        !           601:                 * Don't fire the initial dag in a list, it's fired in
        !           602:                 * rf_State_ExecuteDAG.
        !           603:                 */
        !           604:                for (i = 0; i < desc->numStripes; i++) {
        !           605:                        if ((dagArray[i].numDagsDone < dagArray[i].numDags) &&
        !           606:                            (dagArray[i].numDagsDone ==
        !           607:                             dagArray[i].numDagsFired) &&
        !           608:                            (dagArray[i].numDagsFired > 0)) {
        !           609:                                RF_ETIMER_START(dagArray[i].tracerec.timer);
        !           610:                                /* Fire next dag in this stripe. */
        !           611:                                /*
        !           612:                                 * First, skip to next dag awaiting execution.
        !           613:                                 */
        !           614:                                dag_h = dagArray[i].dags;
        !           615:                                for (j = 0; j < dagArray[i].numDagsDone; j++)
        !           616:                                        dag_h = dag_h->next;
        !           617:                                dagArray[i].numDagsFired++;
        !           618:                                /*
        !           619:                                 * XXX And again we pass a different function
        !           620:                                 * pointer... GO
        !           621:                                 */
        !           622:                                rf_DispatchDAG(dag_h, (void (*) (void *))
        !           623:                                    rf_ContinueDagAccess, &dagArray[i]);
        !           624:                        }
        !           625:                }
        !           626:                return RF_TRUE;
        !           627:        }
        !           628: }
        !           629:
        !           630: /* Only make it this far if all dags complete successfully. */
        !           631: int
        !           632: rf_State_Cleanup(RF_RaidAccessDesc_t *desc)
        !           633: {
        !           634:        RF_AccTraceEntry_t *tracerec = &desc->tracerec;
        !           635:        RF_AccessStripeMapHeader_t *asmh = desc->asmap;
        !           636:        RF_Raid_t *raidPtr = desc->raidPtr;
        !           637:        RF_AccessStripeMap_t *asm_p;
        !           638:        RF_DagHeader_t *dag_h;
        !           639:        RF_Etimer_t timer;
        !           640:        int i;
        !           641:
        !           642:        desc->state++;
        !           643:
        !           644:        timer = tracerec->timer;
        !           645:        RF_ETIMER_STOP(timer);
        !           646:        RF_ETIMER_EVAL(timer);
        !           647:        tracerec->specific.user.dag_retry_us = RF_ETIMER_VAL_US(timer);
        !           648:
        !           649:        /* The RAID I/O is complete. Clean up. */
        !           650:        tracerec->specific.user.dag_retry_us = 0;
        !           651:
        !           652:        RF_ETIMER_START(timer);
        !           653:        if (desc->flags & RF_DAG_RETURN_DAG) {
        !           654:                /* Copy dags into paramDAG. */
        !           655:                *(desc->paramDAG) = desc->dagArray[0].dags;
        !           656:                dag_h = *(desc->paramDAG);
        !           657:                for (i = 1; i < desc->numStripes; i++) {
        !           658:                        /* Concatenate dags from remaining stripes. */
        !           659:                        RF_ASSERT(dag_h);
        !           660:                        while (dag_h->next)
        !           661:                                dag_h = dag_h->next;
        !           662:                        dag_h->next = desc->dagArray[i].dags;
        !           663:                }
        !           664:        } else {
        !           665:                /* Free all dags. */
        !           666:                for (i = 0; i < desc->numStripes; i++) {
        !           667:                        rf_FreeDAG(desc->dagArray[i].dags);
        !           668:                }
        !           669:        }
        !           670:
        !           671:        RF_ETIMER_STOP(timer);
        !           672:        RF_ETIMER_EVAL(timer);
        !           673:        tracerec->specific.user.cleanup_us = RF_ETIMER_VAL_US(timer);
        !           674:
        !           675:        RF_ETIMER_START(timer);
        !           676:        if (!(raidPtr->Layout.map->flags & RF_NO_STRIPE_LOCKS)) {
        !           677:                for (asm_p = asmh->stripeMap; asm_p; asm_p = asm_p->next) {
        !           678:                        if (!rf_suppressLocksAndLargeWrites &&
        !           679:                            asm_p->parityInfo &&
        !           680:                            !(desc->flags & RF_DAG_SUPPRESS_LOCKS)) {
        !           681:                                RF_ASSERT_VALID_LOCKREQ(&asm_p->lockReqDesc);
        !           682:                                rf_ReleaseStripeLock(raidPtr->lockTable,
        !           683:                                    asm_p->stripeID, &asm_p->lockReqDesc);
        !           684:                        }
        !           685:                        if (asm_p->flags & RF_ASM_FLAGS_RECON_BLOCKED) {
        !           686:                                rf_UnblockRecon(raidPtr, asm_p);
        !           687:                        }
        !           688:                }
        !           689:        }
        !           690:        RF_ETIMER_STOP(timer);
        !           691:        RF_ETIMER_EVAL(timer);
        !           692:        tracerec->specific.user.lock_us += RF_ETIMER_VAL_US(timer);
        !           693:
        !           694:        RF_ETIMER_START(timer);
        !           695:        if (desc->flags & RF_DAG_RETURN_ASM)
        !           696:                *(desc->paramASM) = asmh;
        !           697:        else
        !           698:                rf_FreeAccessStripeMap(asmh);
        !           699:        RF_ETIMER_STOP(timer);
        !           700:        RF_ETIMER_EVAL(timer);
        !           701:        tracerec->specific.user.cleanup_us += RF_ETIMER_VAL_US(timer);
        !           702:
        !           703:        RF_ETIMER_STOP(desc->timer);
        !           704:        RF_ETIMER_EVAL(desc->timer);
        !           705:
        !           706:        timer = desc->tracerec.tot_timer;
        !           707:        RF_ETIMER_STOP(timer);
        !           708:        RF_ETIMER_EVAL(timer);
        !           709:        desc->tracerec.total_us = RF_ETIMER_VAL_US(timer);
        !           710:
        !           711:        rf_LogTraceRec(raidPtr, tracerec);
        !           712:
        !           713:        desc->flags |= RF_DAG_ACCESS_COMPLETE;
        !           714:
        !           715:        return RF_FALSE;
        !           716: }

CVSweb