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

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

1.1     ! nbrk        1: /*     $OpenBSD: rf_dagffwr.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $   */
        !             2: /*     $NetBSD: rf_dagffwr.c,v 1.5 2000/01/07 03:40:58 oster Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Mark Holland, Daniel Stodolsky, William V. Courtright II
        !             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: /*
        !            32:  * rf_dagff.c
        !            33:  *
        !            34:  * Code for creating fault-free DAGs.
        !            35:  *
        !            36:  */
        !            37:
        !            38: #include "rf_types.h"
        !            39: #include "rf_raid.h"
        !            40: #include "rf_dag.h"
        !            41: #include "rf_dagutils.h"
        !            42: #include "rf_dagfuncs.h"
        !            43: #include "rf_debugMem.h"
        !            44: #include "rf_dagffrd.h"
        !            45: #include "rf_memchunk.h"
        !            46: #include "rf_general.h"
        !            47: #include "rf_dagffwr.h"
        !            48:
        !            49: /*****************************************************************************
        !            50:  *
        !            51:  * General comments on DAG creation:
        !            52:  *
        !            53:  * All DAGs in this file use roll-away error recovery. Each DAG has a single
        !            54:  * commit node, usually called "Cmt."  If an error occurs before the Cmt node
        !            55:  * is reached, the execution engine will halt forward execution and work
        !            56:  * backward through the graph, executing the undo functions. Assuming that
        !            57:  * each node in the graph prior to the Cmt node are undoable and atomic - or -
        !            58:  * does not make changes to permanent state, the graph will fail atomically.
        !            59:  * If an error occurs after the Cmt node executes, the engine will roll-forward
        !            60:  * through the graph, blindly executing nodes until it reaches the end.
        !            61:  * If a graph reaches the end, it is assumed to have completed successfully.
        !            62:  *
        !            63:  * A graph has only 1 Cmt node.
        !            64:  *
        !            65:  *****************************************************************************/
        !            66:
        !            67:
        !            68: /*****************************************************************************
        !            69:  *
        !            70:  * The following wrappers map the standard DAG creation interface to the
        !            71:  * DAG creation routines. Additionally, these wrappers enable experimentation
        !            72:  * with new DAG structures by providing an extra level of indirection, allowing
        !            73:  * the DAG creation routines to be replaced at this single point.
        !            74:  *
        !            75:  *****************************************************************************/
        !            76:
        !            77:
        !            78: void
        !            79: rf_CreateNonRedundantWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !            80:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !            81:     RF_AllocListElem_t *allocList, RF_IoType_t type)
        !            82: {
        !            83:        rf_CreateNonredundantDAG(raidPtr, asmap, dag_h, bp, flags, allocList,
        !            84:            RF_IO_TYPE_WRITE);
        !            85: }
        !            86:
        !            87: void
        !            88: rf_CreateRAID0WriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !            89:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !            90:     RF_AllocListElem_t *allocList, RF_IoType_t type)
        !            91: {
        !            92:        rf_CreateNonredundantDAG(raidPtr, asmap, dag_h, bp, flags, allocList,
        !            93:            RF_IO_TYPE_WRITE);
        !            94: }
        !            95:
        !            96: void
        !            97: rf_CreateSmallWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !            98:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !            99:     RF_AllocListElem_t *allocList)
        !           100: {
        !           101:        /* "normal" rollaway. */
        !           102:        rf_CommonCreateSmallWriteDAG(raidPtr, asmap, dag_h, bp, flags,
        !           103:            allocList, &rf_xorFuncs, NULL);
        !           104: }
        !           105:
        !           106: void
        !           107: rf_CreateLargeWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !           108:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !           109:     RF_AllocListElem_t *allocList)
        !           110: {
        !           111:        /* "normal" rollaway. */
        !           112:        rf_CommonCreateLargeWriteDAG(raidPtr, asmap, dag_h, bp, flags,
        !           113:            allocList, 1, rf_RegularXorFunc, RF_TRUE);
        !           114: }
        !           115:
        !           116:
        !           117: /*****************************************************************************
        !           118:  *
        !           119:  * DAG creation code begins here.
        !           120:  *
        !           121:  *****************************************************************************/
        !           122:
        !           123:
        !           124: /*****************************************************************************
        !           125:  *
        !           126:  * creates a DAG to perform a large-write operation:
        !           127:  *
        !           128:  *           / Rod \           / Wnd \
        !           129:  * H -- block- Rod - Xor - Cmt - Wnd --- T
        !           130:  *           \ Rod /          \  Wnp /
        !           131:  *                             \[Wnq]/
        !           132:  *
        !           133:  * The XOR node also does the Q calculation in the P+Q architecture.
        !           134:  * All nodes that are before the commit node (Cmt) are assumed to be atomic
        !           135:  * and undoable - or - they make no changes to permanent state.
        !           136:  *
        !           137:  * Rod = read old data
        !           138:  * Cmt = commit node
        !           139:  * Wnp = write new parity
        !           140:  * Wnd = write new data
        !           141:  * Wnq = write new "q"
        !           142:  * [] denotes optional segments in the graph.
        !           143:  *
        !           144:  * Parameters:  raidPtr          - description of the physical array
        !           145:  *             asmap     - logical & physical addresses for this access
        !           146:  *             bp        - buffer ptr (holds write data)
        !           147:  *             flags     - general flags (e.g. disk locking)
        !           148:  *             allocList - list of memory allocated in DAG creation
        !           149:  *             nfaults   - number of faults array can tolerate
        !           150:  *                         (equal to # redundancy units in stripe)
        !           151:  *             redfuncs  - list of redundancy generating functions
        !           152:  *
        !           153:  *****************************************************************************/
        !           154:
        !           155: void
        !           156: rf_CommonCreateLargeWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !           157:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !           158:     RF_AllocListElem_t *allocList, int nfaults, int (*redFunc) (RF_DagNode_t *),
        !           159:     int allowBufferRecycle)
        !           160: {
        !           161:        RF_DagNode_t *nodes, *wndNodes, *rodNodes, *xorNode, *wnpNode;
        !           162:        RF_DagNode_t *wnqNode, *blockNode, *commitNode, *termNode;
        !           163:        int nWndNodes, nRodNodes, i, nodeNum, asmNum;
        !           164:        RF_AccessStripeMapHeader_t *new_asm_h[2];
        !           165:        RF_StripeNum_t parityStripeID;
        !           166:        char *sosBuffer, *eosBuffer;
        !           167:        RF_ReconUnitNum_t which_ru;
        !           168:        RF_RaidLayout_t *layoutPtr;
        !           169:        RF_PhysDiskAddr_t *pda;
        !           170:
        !           171:        layoutPtr = &(raidPtr->Layout);
        !           172:        parityStripeID = rf_RaidAddressToParityStripeID(layoutPtr,
        !           173:            asmap->raidAddress, &which_ru);
        !           174:
        !           175:        if (rf_dagDebug) {
        !           176:                printf("[Creating large-write DAG]\n");
        !           177:        }
        !           178:        dag_h->creator = "LargeWriteDAG";
        !           179:
        !           180:        dag_h->numCommitNodes = 1;
        !           181:        dag_h->numCommits = 0;
        !           182:        dag_h->numSuccedents = 1;
        !           183:
        !           184:        /* Alloc the nodes: Wnd, xor, commit, block, term, and  Wnp. */
        !           185:        nWndNodes = asmap->numStripeUnitsAccessed;
        !           186:        RF_CallocAndAdd(nodes, nWndNodes + 4 + nfaults, sizeof(RF_DagNode_t),
        !           187:            (RF_DagNode_t *), allocList);
        !           188:        i = 0;
        !           189:        wndNodes = &nodes[i];
        !           190:        i += nWndNodes;
        !           191:        xorNode = &nodes[i];
        !           192:        i += 1;
        !           193:        wnpNode = &nodes[i];
        !           194:        i += 1;
        !           195:        blockNode = &nodes[i];
        !           196:        i += 1;
        !           197:        commitNode = &nodes[i];
        !           198:        i += 1;
        !           199:        termNode = &nodes[i];
        !           200:        i += 1;
        !           201:        if (nfaults == 2) {
        !           202:                wnqNode = &nodes[i];
        !           203:                i += 1;
        !           204:        } else {
        !           205:                wnqNode = NULL;
        !           206:        }
        !           207:        rf_MapUnaccessedPortionOfStripe(raidPtr, layoutPtr, asmap, dag_h,
        !           208:            new_asm_h, &nRodNodes, &sosBuffer, &eosBuffer, allocList);
        !           209:        if (nRodNodes > 0) {
        !           210:                RF_CallocAndAdd(rodNodes, nRodNodes, sizeof(RF_DagNode_t),
        !           211:                    (RF_DagNode_t *), allocList);
        !           212:        } else {
        !           213:                rodNodes = NULL;
        !           214:        }
        !           215:
        !           216:        /* Begin node initialization. */
        !           217:        if (nRodNodes > 0) {
        !           218:                rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           219:                    rf_NullNodeUndoFunc, NULL, nRodNodes, 0, 0, 0, dag_h,
        !           220:                    "Nil", allocList);
        !           221:        } else {
        !           222:                rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           223:                    rf_NullNodeUndoFunc, NULL, 1, 0, 0, 0, dag_h, "Nil",
        !           224:                    allocList);
        !           225:        }
        !           226:
        !           227:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           228:            rf_NullNodeUndoFunc, NULL, nWndNodes + nfaults, 1, 0, 0,
        !           229:            dag_h, "Cmt", allocList);
        !           230:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           231:            rf_TerminateUndoFunc, NULL, 0, nWndNodes + nfaults, 0, 0,
        !           232:            dag_h, "Trm", allocList);
        !           233:
        !           234:        /* Initialize the Rod nodes. */
        !           235:        for (nodeNum = asmNum = 0; asmNum < 2; asmNum++) {
        !           236:                if (new_asm_h[asmNum]) {
        !           237:                        pda = new_asm_h[asmNum]->stripeMap->physInfo;
        !           238:                        while (pda) {
        !           239:                                rf_InitNode(&rodNodes[nodeNum], rf_wait,
        !           240:                                    RF_FALSE, rf_DiskReadFunc,
        !           241:                                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !           242:                                    1, 1, 4, 0, dag_h, "Rod", allocList);
        !           243:                                rodNodes[nodeNum].params[0].p = pda;
        !           244:                                rodNodes[nodeNum].params[1].p = pda->bufPtr;
        !           245:                                rodNodes[nodeNum].params[2].v = parityStripeID;
        !           246:                                rodNodes[nodeNum].params[3].v =
        !           247:                                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           248:                                    0, 0, which_ru);
        !           249:                                nodeNum++;
        !           250:                                pda = pda->next;
        !           251:                        }
        !           252:                }
        !           253:        }
        !           254:        RF_ASSERT(nodeNum == nRodNodes);
        !           255:
        !           256:        /* Initialize the wnd nodes. */
        !           257:        pda = asmap->physInfo;
        !           258:        for (i = 0; i < nWndNodes; i++) {
        !           259:                rf_InitNode(&wndNodes[i], rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !           260:                    rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           261:                    dag_h, "Wnd", allocList);
        !           262:                RF_ASSERT(pda != NULL);
        !           263:                wndNodes[i].params[0].p = pda;
        !           264:                wndNodes[i].params[1].p = pda->bufPtr;
        !           265:                wndNodes[i].params[2].v = parityStripeID;
        !           266:                wndNodes[i].params[3].v =
        !           267:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           268:                pda = pda->next;
        !           269:        }
        !           270:
        !           271:        /* Initialize the redundancy node. */
        !           272:        if (nRodNodes > 0) {
        !           273:                rf_InitNode(xorNode, rf_wait, RF_FALSE, redFunc,
        !           274:                    rf_NullNodeUndoFunc, NULL, 1, nRodNodes,
        !           275:                    2 * (nWndNodes + nRodNodes) + 1, nfaults, dag_h,
        !           276:                    "Xr ", allocList);
        !           277:        } else {
        !           278:                rf_InitNode(xorNode, rf_wait, RF_FALSE, redFunc,
        !           279:                    rf_NullNodeUndoFunc, NULL, 1, 1,
        !           280:                    2 * (nWndNodes + nRodNodes) + 1, nfaults, dag_h,
        !           281:                    "Xr ", allocList);
        !           282:        }
        !           283:        xorNode->flags |= RF_DAGNODE_FLAG_YIELD;
        !           284:        for (i = 0; i < nWndNodes; i++) {
        !           285:                xorNode->params[2 * i + 0] =
        !           286:                    wndNodes[i].params[0];      /* pda */
        !           287:                xorNode->params[2 * i + 1] =
        !           288:                    wndNodes[i].params[1];      /* buf ptr */
        !           289:        }
        !           290:        for (i = 0; i < nRodNodes; i++) {
        !           291:                xorNode->params[2 * (nWndNodes + i) + 0] =
        !           292:                    rodNodes[i].params[0];      /* pda */
        !           293:                xorNode->params[2 * (nWndNodes + i) + 1] =
        !           294:                    rodNodes[i].params[1];      /* buf ptr */
        !           295:        }
        !           296:        /* Xor node needs to get at RAID information. */
        !           297:        xorNode->params[2 * (nWndNodes + nRodNodes)].p = raidPtr;
        !           298:
        !           299:        /*
        !           300:         * Look for an Rod node that reads a complete SU. If none, alloc
        !           301:         * a buffer to receive the parity info. Note that we can't use a
        !           302:         * new data buffer because it will not have gotten written when
        !           303:         * the xor occurs.
        !           304:         */
        !           305:        if (allowBufferRecycle) {
        !           306:                for (i = 0; i < nRodNodes; i++) {
        !           307:                        if (((RF_PhysDiskAddr_t *) rodNodes[i].params[0].p)
        !           308:                            ->numSector == raidPtr->Layout.sectorsPerStripeUnit)
        !           309:                                break;
        !           310:                }
        !           311:        }
        !           312:        if ((!allowBufferRecycle) || (i == nRodNodes)) {
        !           313:                RF_CallocAndAdd(xorNode->results[0], 1,
        !           314:                    rf_RaidAddressToByte(raidPtr,
        !           315:                    raidPtr->Layout.sectorsPerStripeUnit),
        !           316:                    (void *), allocList);
        !           317:        } else {
        !           318:                xorNode->results[0] = rodNodes[i].params[1].p;
        !           319:        }
        !           320:
        !           321:        /* Initialize the Wnp node. */
        !           322:        rf_InitNode(wnpNode, rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !           323:            rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           324:            dag_h, "Wnp", allocList);
        !           325:        wnpNode->params[0].p = asmap->parityInfo;
        !           326:        wnpNode->params[1].p = xorNode->results[0];
        !           327:        wnpNode->params[2].v = parityStripeID;
        !           328:        wnpNode->params[3].v =
        !           329:            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           330:        /* parityInfo must describe entire parity unit. */
        !           331:        RF_ASSERT(asmap->parityInfo->next == NULL);
        !           332:
        !           333:        if (nfaults == 2) {
        !           334:                /*
        !           335:                 * We never try to recycle a buffer for the Q calculation
        !           336:                 * in addition to the parity. This would cause two buffers
        !           337:                 * to get smashed during the P and Q calculation, guaranteeing
        !           338:                 * one would be wrong.
        !           339:                 */
        !           340:                RF_CallocAndAdd(xorNode->results[1], 1,
        !           341:                    rf_RaidAddressToByte(raidPtr,
        !           342:                     raidPtr->Layout.sectorsPerStripeUnit),
        !           343:                    (void *), allocList);
        !           344:                rf_InitNode(wnqNode, rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !           345:                    rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           346:                    dag_h, "Wnq", allocList);
        !           347:                wnqNode->params[0].p = asmap->qInfo;
        !           348:                wnqNode->params[1].p = xorNode->results[1];
        !           349:                wnqNode->params[2].v = parityStripeID;
        !           350:                wnqNode->params[3].v =
        !           351:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           352:                /* parityInfo must describe entire parity unit. */
        !           353:                RF_ASSERT(asmap->parityInfo->next == NULL);
        !           354:        }
        !           355:        /*
        !           356:         * Connect nodes to form graph.
        !           357:         */
        !           358:
        !           359:        /* Connect dag header to block node. */
        !           360:        RF_ASSERT(blockNode->numAntecedents == 0);
        !           361:        dag_h->succedents[0] = blockNode;
        !           362:
        !           363:        if (nRodNodes > 0) {
        !           364:                /* Connect the block node to the Rod nodes. */
        !           365:                RF_ASSERT(blockNode->numSuccedents == nRodNodes);
        !           366:                RF_ASSERT(xorNode->numAntecedents == nRodNodes);
        !           367:                for (i = 0; i < nRodNodes; i++) {
        !           368:                        RF_ASSERT(rodNodes[i].numAntecedents == 1);
        !           369:                        blockNode->succedents[i] = &rodNodes[i];
        !           370:                        rodNodes[i].antecedents[0] = blockNode;
        !           371:                        rodNodes[i].antType[0] = rf_control;
        !           372:
        !           373:                        /* Connect the Rod nodes to the Xor node. */
        !           374:                        RF_ASSERT(rodNodes[i].numSuccedents == 1);
        !           375:                        rodNodes[i].succedents[0] = xorNode;
        !           376:                        xorNode->antecedents[i] = &rodNodes[i];
        !           377:                        xorNode->antType[i] = rf_trueData;
        !           378:                }
        !           379:        } else {
        !           380:                /* Connect the block node to the Xor node. */
        !           381:                RF_ASSERT(blockNode->numSuccedents == 1);
        !           382:                RF_ASSERT(xorNode->numAntecedents == 1);
        !           383:                blockNode->succedents[0] = xorNode;
        !           384:                xorNode->antecedents[0] = blockNode;
        !           385:                xorNode->antType[0] = rf_control;
        !           386:        }
        !           387:
        !           388:        /* Connect the xor node to the commit node. */
        !           389:        RF_ASSERT(xorNode->numSuccedents == 1);
        !           390:        RF_ASSERT(commitNode->numAntecedents == 1);
        !           391:        xorNode->succedents[0] = commitNode;
        !           392:        commitNode->antecedents[0] = xorNode;
        !           393:        commitNode->antType[0] = rf_control;
        !           394:
        !           395:        /* Connect the commit node to the write nodes. */
        !           396:        RF_ASSERT(commitNode->numSuccedents == nWndNodes + nfaults);
        !           397:        for (i = 0; i < nWndNodes; i++) {
        !           398:                RF_ASSERT(wndNodes->numAntecedents == 1);
        !           399:                commitNode->succedents[i] = &wndNodes[i];
        !           400:                wndNodes[i].antecedents[0] = commitNode;
        !           401:                wndNodes[i].antType[0] = rf_control;
        !           402:        }
        !           403:        RF_ASSERT(wnpNode->numAntecedents == 1);
        !           404:        commitNode->succedents[nWndNodes] = wnpNode;
        !           405:        wnpNode->antecedents[0] = commitNode;
        !           406:        wnpNode->antType[0] = rf_trueData;
        !           407:        if (nfaults == 2) {
        !           408:                RF_ASSERT(wnqNode->numAntecedents == 1);
        !           409:                commitNode->succedents[nWndNodes + 1] = wnqNode;
        !           410:                wnqNode->antecedents[0] = commitNode;
        !           411:                wnqNode->antType[0] = rf_trueData;
        !           412:        }
        !           413:        /* Connect the write nodes to the term node. */
        !           414:        RF_ASSERT(termNode->numAntecedents == nWndNodes + nfaults);
        !           415:        RF_ASSERT(termNode->numSuccedents == 0);
        !           416:        for (i = 0; i < nWndNodes; i++) {
        !           417:                RF_ASSERT(wndNodes->numSuccedents == 1);
        !           418:                wndNodes[i].succedents[0] = termNode;
        !           419:                termNode->antecedents[i] = &wndNodes[i];
        !           420:                termNode->antType[i] = rf_control;
        !           421:        }
        !           422:        RF_ASSERT(wnpNode->numSuccedents == 1);
        !           423:        wnpNode->succedents[0] = termNode;
        !           424:        termNode->antecedents[nWndNodes] = wnpNode;
        !           425:        termNode->antType[nWndNodes] = rf_control;
        !           426:        if (nfaults == 2) {
        !           427:                RF_ASSERT(wnqNode->numSuccedents == 1);
        !           428:                wnqNode->succedents[0] = termNode;
        !           429:                termNode->antecedents[nWndNodes + 1] = wnqNode;
        !           430:                termNode->antType[nWndNodes + 1] = rf_control;
        !           431:        }
        !           432: }
        !           433: /*****************************************************************************
        !           434:  *
        !           435:  * Create a DAG to perform a small-write operation (either raid 5 or pq),
        !           436:  * which is as follows:
        !           437:  *
        !           438:  * Hdr -> Nil -> Rop -> Xor -> Cmt ----> Wnp [Unp] --> Trm
        !           439:  *            \- Rod X      /     \----> Wnd [Und]-/
        !           440:  *           [\- Rod X     /       \---> Wnd [Und]-/]
        !           441:  *           [\- Roq -> Q /         \--> Wnq [Unq]-/]
        !           442:  *
        !           443:  * Rop = read old parity
        !           444:  * Rod = read old data
        !           445:  * Roq = read old "q"
        !           446:  * Cmt = commit node
        !           447:  * Und = unlock data disk
        !           448:  * Unp = unlock parity disk
        !           449:  * Unq = unlock q disk
        !           450:  * Wnp = write new parity
        !           451:  * Wnd = write new data
        !           452:  * Wnq = write new "q"
        !           453:  * [ ] denotes optional segments in the graph.
        !           454:  *
        !           455:  * Parameters: raidPtr   - description of the physical array
        !           456:  *             asmap     - logical & physical addresses for this access
        !           457:  *             bp        - buffer ptr (holds write data)
        !           458:  *             flags     - general flags (e.g. disk locking)
        !           459:  *             allocList - list of memory allocated in DAG creation
        !           460:  *             pfuncs    - list of parity generating functions
        !           461:  *             qfuncs    - list of q generating functions
        !           462:  *
        !           463:  * A null qfuncs indicates single fault tolerant.
        !           464:  *****************************************************************************/
        !           465:
        !           466: void
        !           467: rf_CommonCreateSmallWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !           468:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !           469:     RF_AllocListElem_t *allocList, RF_RedFuncs_t *pfuncs, RF_RedFuncs_t *qfuncs)
        !           470: {
        !           471:        RF_DagNode_t *readDataNodes, *readParityNodes, *readQNodes, *termNode;
        !           472:        RF_DagNode_t *unlockDataNodes, *unlockParityNodes, *unlockQNodes;
        !           473:        RF_DagNode_t *xorNodes, *qNodes, *blockNode, *commitNode, *nodes;
        !           474:        RF_DagNode_t *writeDataNodes, *writeParityNodes, *writeQNodes;
        !           475:        int i, j, nNodes, totalNumNodes, lu_flag;
        !           476:        RF_ReconUnitNum_t which_ru;
        !           477:        int (*func) (RF_DagNode_t *);
        !           478:        int (*undoFunc) (RF_DagNode_t *);
        !           479:        int (*qfunc) (RF_DagNode_t *);
        !           480:        int numDataNodes, numParityNodes;
        !           481:        RF_StripeNum_t parityStripeID;
        !           482:        RF_PhysDiskAddr_t *pda;
        !           483:        char *name, *qname;
        !           484:        long nfaults;
        !           485:
        !           486:        nfaults = qfuncs ? 2 : 1;
        !           487:        lu_flag = (rf_enableAtomicRMW) ? 1 : 0; /* Lock/unlock flag. */
        !           488:
        !           489:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !           490:            asmap->raidAddress, &which_ru);
        !           491:        pda = asmap->physInfo;
        !           492:        numDataNodes = asmap->numStripeUnitsAccessed;
        !           493:        numParityNodes = (asmap->parityInfo->next) ? 2 : 1;
        !           494:
        !           495:        if (rf_dagDebug) {
        !           496:                printf("[Creating small-write DAG]\n");
        !           497:        }
        !           498:        RF_ASSERT(numDataNodes > 0);
        !           499:        dag_h->creator = "SmallWriteDAG";
        !           500:
        !           501:        dag_h->numCommitNodes = 1;
        !           502:        dag_h->numCommits = 0;
        !           503:        dag_h->numSuccedents = 1;
        !           504:
        !           505:        /*
        !           506:         * DAG creation occurs in four steps:
        !           507:         * 1. Count the number of nodes in the DAG.
        !           508:         * 2. Create the nodes.
        !           509:         * 3. Initialize the nodes.
        !           510:         * 4. Connect the nodes.
        !           511:         */
        !           512:
        !           513:        /*
        !           514:         * Step 1. Compute number of nodes in the graph.
        !           515:         */
        !           516:
        !           517:        /*
        !           518:         * Number of nodes: a read and write for each data unit, a redundancy
        !           519:         * computation node for each parity node (nfaults * nparity), a read
        !           520:         * and write for each parity unit, a block and commit node (2), a
        !           521:         * terminate node if atomic RMW, an unlock node for each
        !           522:         * data/redundancy unit.
        !           523:         */
        !           524:        totalNumNodes = (2 * numDataNodes) + (nfaults * numParityNodes)
        !           525:            + (nfaults * 2 * numParityNodes) + 3;
        !           526:        if (lu_flag) {
        !           527:                totalNumNodes += (numDataNodes + (nfaults * numParityNodes));
        !           528:        }
        !           529:        /*
        !           530:         * Step 2. Create the nodes.
        !           531:         */
        !           532:        RF_CallocAndAdd(nodes, totalNumNodes, sizeof(RF_DagNode_t),
        !           533:            (RF_DagNode_t *), allocList);
        !           534:        i = 0;
        !           535:        blockNode = &nodes[i];
        !           536:        i += 1;
        !           537:        commitNode = &nodes[i];
        !           538:        i += 1;
        !           539:        readDataNodes = &nodes[i];
        !           540:        i += numDataNodes;
        !           541:        readParityNodes = &nodes[i];
        !           542:        i += numParityNodes;
        !           543:        writeDataNodes = &nodes[i];
        !           544:        i += numDataNodes;
        !           545:        writeParityNodes = &nodes[i];
        !           546:        i += numParityNodes;
        !           547:        xorNodes = &nodes[i];
        !           548:        i += numParityNodes;
        !           549:        termNode = &nodes[i];
        !           550:        i += 1;
        !           551:        if (lu_flag) {
        !           552:                unlockDataNodes = &nodes[i];
        !           553:                i += numDataNodes;
        !           554:                unlockParityNodes = &nodes[i];
        !           555:                i += numParityNodes;
        !           556:        } else {
        !           557:                unlockDataNodes = unlockParityNodes = NULL;
        !           558:        }
        !           559:        if (nfaults == 2) {
        !           560:                readQNodes = &nodes[i];
        !           561:                i += numParityNodes;
        !           562:                writeQNodes = &nodes[i];
        !           563:                i += numParityNodes;
        !           564:                qNodes = &nodes[i];
        !           565:                i += numParityNodes;
        !           566:                if (lu_flag) {
        !           567:                        unlockQNodes = &nodes[i];
        !           568:                        i += numParityNodes;
        !           569:                } else {
        !           570:                        unlockQNodes = NULL;
        !           571:                }
        !           572:        } else {
        !           573:                readQNodes = writeQNodes = qNodes = unlockQNodes = NULL;
        !           574:        }
        !           575:        RF_ASSERT(i == totalNumNodes);
        !           576:
        !           577:        /*
        !           578:         * Step 3. Initialize the nodes.
        !           579:         */
        !           580:        /* Initialize block node (Nil). */
        !           581:        nNodes = numDataNodes + (nfaults * numParityNodes);
        !           582:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           583:            rf_NullNodeUndoFunc, NULL, nNodes, 0, 0, 0, dag_h,
        !           584:            "Nil", allocList);
        !           585:
        !           586:        /* Initialize commit node (Cmt). */
        !           587:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           588:            rf_NullNodeUndoFunc, NULL, nNodes, (nfaults * numParityNodes),
        !           589:            0, 0, dag_h, "Cmt", allocList);
        !           590:
        !           591:        /* Initialize terminate node (Trm). */
        !           592:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           593:            rf_TerminateUndoFunc, NULL, 0, nNodes, 0, 0, dag_h,
        !           594:            "Trm", allocList);
        !           595:
        !           596:        /* Initialize nodes which read old data (Rod). */
        !           597:        for (i = 0; i < numDataNodes; i++) {
        !           598:                rf_InitNode(&readDataNodes[i], rf_wait, RF_FALSE,
        !           599:                    rf_DiskReadFunc, rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !           600:                    (nfaults * numParityNodes), 1, 4, 0, dag_h, "Rod",
        !           601:                    allocList);
        !           602:                RF_ASSERT(pda != NULL);
        !           603:                /* Physical disk addr desc. */
        !           604:                readDataNodes[i].params[0].p = pda;
        !           605:                /* Buffer to hold old data. */
        !           606:                readDataNodes[i].params[1].p = rf_AllocBuffer(raidPtr,
        !           607:                    dag_h, pda, allocList);
        !           608:                readDataNodes[i].params[2].v = parityStripeID;
        !           609:                readDataNodes[i].params[3].v =
        !           610:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           611:                    lu_flag, 0, which_ru);
        !           612:                pda = pda->next;
        !           613:                for (j = 0; j < readDataNodes[i].numSuccedents; j++) {
        !           614:                        readDataNodes[i].propList[j] = NULL;
        !           615:                }
        !           616:        }
        !           617:
        !           618:        /* Initialize nodes which read old parity (Rop). */
        !           619:        pda = asmap->parityInfo;
        !           620:        i = 0;
        !           621:        for (i = 0; i < numParityNodes; i++) {
        !           622:                RF_ASSERT(pda != NULL);
        !           623:                rf_InitNode(&readParityNodes[i], rf_wait, RF_FALSE,
        !           624:                    rf_DiskReadFunc, rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !           625:                    numParityNodes, 1, 4, 0, dag_h, "Rop", allocList);
        !           626:                readParityNodes[i].params[0].p = pda;
        !           627:                /* Buffer to hold old parity. */
        !           628:                readParityNodes[i].params[1].p = rf_AllocBuffer(raidPtr,
        !           629:                    dag_h, pda, allocList);
        !           630:                readParityNodes[i].params[2].v = parityStripeID;
        !           631:                readParityNodes[i].params[3].v =
        !           632:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           633:                    lu_flag, 0, which_ru);
        !           634:                pda = pda->next;
        !           635:                for (j = 0; j < readParityNodes[i].numSuccedents; j++) {
        !           636:                        readParityNodes[i].propList[0] = NULL;
        !           637:                }
        !           638:        }
        !           639:
        !           640:        /* Initialize nodes which read old Q (Roq). */
        !           641:        if (nfaults == 2) {
        !           642:                pda = asmap->qInfo;
        !           643:                for (i = 0; i < numParityNodes; i++) {
        !           644:                        RF_ASSERT(pda != NULL);
        !           645:                        rf_InitNode(&readQNodes[i], rf_wait, RF_FALSE,
        !           646:                            rf_DiskReadFunc, rf_DiskReadUndoFunc,
        !           647:                            rf_GenericWakeupFunc, numParityNodes,
        !           648:                            1, 4, 0, dag_h, "Roq", allocList);
        !           649:                        readQNodes[i].params[0].p = pda;
        !           650:                        /* Buffer to hold old Q. */
        !           651:                        readQNodes[i].params[1].p = rf_AllocBuffer(raidPtr,
        !           652:                            dag_h, pda, allocList);
        !           653:                        readQNodes[i].params[2].v = parityStripeID;
        !           654:                        readQNodes[i].params[3].v =
        !           655:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           656:                            lu_flag, 0, which_ru);
        !           657:                        pda = pda->next;
        !           658:                        for (j = 0; j < readQNodes[i].numSuccedents; j++) {
        !           659:                                readQNodes[i].propList[0] = NULL;
        !           660:                        }
        !           661:                }
        !           662:        }
        !           663:        /* Initialize nodes which write new data (Wnd). */
        !           664:        pda = asmap->physInfo;
        !           665:        for (i = 0; i < numDataNodes; i++) {
        !           666:                RF_ASSERT(pda != NULL);
        !           667:                rf_InitNode(&writeDataNodes[i], rf_wait, RF_FALSE,
        !           668:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !           669:                    rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           670:                    "Wnd", allocList);
        !           671:                /* Physical disk addr desc. */
        !           672:                writeDataNodes[i].params[0].p = pda;
        !           673:                /* Buffer holding new data to be written. */
        !           674:                writeDataNodes[i].params[1].p = pda->bufPtr;
        !           675:                writeDataNodes[i].params[2].v = parityStripeID;
        !           676:                writeDataNodes[i].params[3].v =
        !           677:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           678:                if (lu_flag) {
        !           679:                        /* Initialize node to unlock the disk queue. */
        !           680:                        rf_InitNode(&unlockDataNodes[i], rf_wait, RF_FALSE,
        !           681:                            rf_DiskUnlockFunc, rf_DiskUnlockUndoFunc,
        !           682:                            rf_GenericWakeupFunc, 1, 1, 2, 0, dag_h,
        !           683:                            "Und", allocList);
        !           684:                        /* Physical disk addr desc. */
        !           685:                        unlockDataNodes[i].params[0].p = pda;
        !           686:                        unlockDataNodes[i].params[1].v =
        !           687:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           688:                            0, lu_flag, which_ru);
        !           689:                }
        !           690:                pda = pda->next;
        !           691:        }
        !           692:
        !           693:        /*
        !           694:         * Initialize nodes which compute new parity and Q.
        !           695:         */
        !           696:        /*
        !           697:         * We use the simple XOR func in the double-XOR case, and when
        !           698:         * we're accessing only a portion of one stripe unit.
        !           699:         * The distinction between the two is that the regular XOR func
        !           700:         * assumes that the targbuf is a full SU in size, and examines
        !           701:         * the pda associated with the buffer to decide where within
        !           702:         * the buffer to XOR the data, whereas the simple XOR func just
        !           703:         * XORs the data into the start of the buffer.
        !           704:         */
        !           705:        if ((numParityNodes == 2) || ((numDataNodes == 1) &&
        !           706:            (asmap->totalSectorsAccessed <
        !           707:             raidPtr->Layout.sectorsPerStripeUnit))) {
        !           708:                func = pfuncs->simple;
        !           709:                undoFunc = rf_NullNodeUndoFunc;
        !           710:                name = pfuncs->SimpleName;
        !           711:                if (qfuncs) {
        !           712:                        qfunc = qfuncs->simple;
        !           713:                        qname = qfuncs->SimpleName;
        !           714:                } else {
        !           715:                        qfunc = NULL;
        !           716:                        qname = NULL;
        !           717:                }
        !           718:        } else {
        !           719:                func = pfuncs->regular;
        !           720:                undoFunc = rf_NullNodeUndoFunc;
        !           721:                name = pfuncs->RegularName;
        !           722:                if (qfuncs) {
        !           723:                        qfunc = qfuncs->regular;
        !           724:                        qname = qfuncs->RegularName;
        !           725:                } else {
        !           726:                        qfunc = NULL;
        !           727:                        qname = NULL;
        !           728:                }
        !           729:        }
        !           730:        /*
        !           731:         * Initialize the xor nodes: params are {pda,buf}.
        !           732:         * From {Rod,Wnd,Rop} nodes, and raidPtr.
        !           733:         */
        !           734:        if (numParityNodes == 2) {
        !           735:                /* Double-xor case. */
        !           736:                for (i = 0; i < numParityNodes; i++) {
        !           737:                        /* Note: no wakeup func for xor. */
        !           738:                        rf_InitNode(&xorNodes[i], rf_wait, RF_FALSE, func,
        !           739:                            undoFunc, NULL, 1, (numDataNodes + numParityNodes),
        !           740:                            7, 1, dag_h, name, allocList);
        !           741:                        xorNodes[i].flags |= RF_DAGNODE_FLAG_YIELD;
        !           742:                        xorNodes[i].params[0] = readDataNodes[i].params[0];
        !           743:                        xorNodes[i].params[1] = readDataNodes[i].params[1];
        !           744:                        xorNodes[i].params[2] = readParityNodes[i].params[0];
        !           745:                        xorNodes[i].params[3] = readParityNodes[i].params[1];
        !           746:                        xorNodes[i].params[4] = writeDataNodes[i].params[0];
        !           747:                        xorNodes[i].params[5] = writeDataNodes[i].params[1];
        !           748:                        xorNodes[i].params[6].p = raidPtr;
        !           749:                        /* Use old parity buf as target buf. */
        !           750:                        xorNodes[i].results[0] = readParityNodes[i].params[1].p;
        !           751:                        if (nfaults == 2) {
        !           752:                                /* Note: no wakeup func for qor. */
        !           753:                                rf_InitNode(&qNodes[i], rf_wait, RF_FALSE,
        !           754:                                    qfunc, undoFunc, NULL, 1,
        !           755:                                    (numDataNodes + numParityNodes), 7, 1,
        !           756:                                    dag_h, qname, allocList);
        !           757:                                qNodes[i].params[0] =
        !           758:                                    readDataNodes[i].params[0];
        !           759:                                qNodes[i].params[1] =
        !           760:                                    readDataNodes[i].params[1];
        !           761:                                qNodes[i].params[2] = readQNodes[i].params[0];
        !           762:                                qNodes[i].params[3] = readQNodes[i].params[1];
        !           763:                                qNodes[i].params[4] =
        !           764:                                    writeDataNodes[i].params[0];
        !           765:                                qNodes[i].params[5] =
        !           766:                                    writeDataNodes[i].params[1];
        !           767:                                qNodes[i].params[6].p = raidPtr;
        !           768:                                /* Use old Q buf as target buf. */
        !           769:                                qNodes[i].results[0] =
        !           770:                                    readQNodes[i].params[1].p;
        !           771:                        }
        !           772:                }
        !           773:        } else {
        !           774:                /* There is only one xor node in this case. */
        !           775:                rf_InitNode(&xorNodes[0], rf_wait, RF_FALSE, func, undoFunc,
        !           776:                    NULL, 1, (numDataNodes + numParityNodes),
        !           777:                    (2 * (numDataNodes + numDataNodes + 1) + 1), 1,
        !           778:                    dag_h, name, allocList);
        !           779:                xorNodes[0].flags |= RF_DAGNODE_FLAG_YIELD;
        !           780:                for (i = 0; i < numDataNodes + 1; i++) {
        !           781:                        /* Set up params related to Rod and Rop nodes. */
        !           782:                        xorNodes[0].params[2 * i + 0] =
        !           783:                            readDataNodes[i].params[0]; /* pda */
        !           784:                        xorNodes[0].params[2 * i + 1] =
        !           785:                            readDataNodes[i].params[1]; /* buffer ptr */
        !           786:                }
        !           787:                for (i = 0; i < numDataNodes; i++) {
        !           788:                        /* Set up params related to Wnd and Wnp nodes. */
        !           789:                        xorNodes[0].params[2 * (numDataNodes + 1 + i) + 0] =
        !           790:                            writeDataNodes[i].params[0];        /* pda */
        !           791:                        xorNodes[0].params[2 * (numDataNodes + 1 + i) + 1] =
        !           792:                            writeDataNodes[i].params[1];        /* buffer ptr */
        !           793:                }
        !           794:                /* Xor node needs to get at RAID information. */
        !           795:                xorNodes[0].params[2 * (numDataNodes + numDataNodes + 1)].p =
        !           796:                    raidPtr;
        !           797:                xorNodes[0].results[0] = readParityNodes[0].params[1].p;
        !           798:                if (nfaults == 2) {
        !           799:                        rf_InitNode(&qNodes[0], rf_wait, RF_FALSE, qfunc,
        !           800:                            undoFunc, NULL, 1, (numDataNodes + numParityNodes),
        !           801:                            (2 * (numDataNodes + numDataNodes + 1) + 1), 1,
        !           802:                            dag_h, qname, allocList);
        !           803:                        for (i = 0; i < numDataNodes; i++) {
        !           804:                                /* Set up params related to Rod. */
        !           805:                                qNodes[0].params[2 * i + 0] =
        !           806:                                    readDataNodes[i].params[0]; /* pda */
        !           807:                                qNodes[0].params[2 * i + 1] =
        !           808:                                    readDataNodes[i].params[1]; /* buffer ptr */
        !           809:                        }
        !           810:                        /* And read old q. */
        !           811:                        qNodes[0].params[2 * numDataNodes + 0] =
        !           812:                            readQNodes[0].params[0];    /* pda */
        !           813:                        qNodes[0].params[2 * numDataNodes + 1] =
        !           814:                            readQNodes[0].params[1];    /* buffer ptr */
        !           815:                        for (i = 0; i < numDataNodes; i++) {
        !           816:                                /* Set up params related to Wnd nodes. */
        !           817:                                qNodes[0].params
        !           818:                                    [2 * (numDataNodes + 1 + i) + 0] =
        !           819:                                    /* pda */
        !           820:                                    writeDataNodes[i].params[0];
        !           821:                                qNodes[0].params
        !           822:                                    [2 * (numDataNodes + 1 + i) + 1] =
        !           823:                                    /* buffer ptr */
        !           824:                                    writeDataNodes[i].params[1];
        !           825:                        }
        !           826:                        /* Xor node needs to get at RAID information. */
        !           827:                        qNodes[0].params
        !           828:                            [2 * (numDataNodes + numDataNodes + 1)].p = raidPtr;
        !           829:                        qNodes[0].results[0] = readQNodes[0].params[1].p;
        !           830:                }
        !           831:        }
        !           832:
        !           833:        /* Initialize nodes which write new parity (Wnp). */
        !           834:        pda = asmap->parityInfo;
        !           835:        for (i = 0; i < numParityNodes; i++) {
        !           836:                rf_InitNode(&writeParityNodes[i], rf_wait, RF_FALSE,
        !           837:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !           838:                    rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           839:                    "Wnp", allocList);
        !           840:                RF_ASSERT(pda != NULL);
        !           841:                /* Param 1 (bufPtr) filled in by xor node. */
        !           842:                writeParityNodes[i].params[0].p = pda;
        !           843:                /* Buffer pointer for parity write operation. */
        !           844:                writeParityNodes[i].params[1].p = xorNodes[i].results[0];
        !           845:                writeParityNodes[i].params[2].v = parityStripeID;
        !           846:                writeParityNodes[i].params[3].v =
        !           847:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           848:                if (lu_flag) {
        !           849:                        /* Initialize node to unlock the disk queue. */
        !           850:                        rf_InitNode(&unlockParityNodes[i], rf_wait, RF_FALSE,
        !           851:                            rf_DiskUnlockFunc, rf_DiskUnlockUndoFunc,
        !           852:                            rf_GenericWakeupFunc, 1, 1, 2, 0, dag_h,
        !           853:                            "Unp", allocList);
        !           854:                        /* Physical disk addr desc. */
        !           855:                        unlockParityNodes[i].params[0].p = pda;
        !           856:                        unlockParityNodes[i].params[1].v =
        !           857:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           858:                            0, lu_flag, which_ru);
        !           859:                }
        !           860:                pda = pda->next;
        !           861:        }
        !           862:
        !           863:        /* Initialize nodes which write new Q (Wnq). */
        !           864:        if (nfaults == 2) {
        !           865:                pda = asmap->qInfo;
        !           866:                for (i = 0; i < numParityNodes; i++) {
        !           867:                        rf_InitNode(&writeQNodes[i], rf_wait, RF_FALSE,
        !           868:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !           869:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           870:                            "Wnq", allocList);
        !           871:                        RF_ASSERT(pda != NULL);
        !           872:                        /* Param 1 (bufPtr) filled in by xor node. */
        !           873:                        writeQNodes[i].params[0].p = pda;
        !           874:                        writeQNodes[i].params[1].p = qNodes[i].results[0];
        !           875:                        /* Buffer pointer for parity write operation. */
        !           876:                        writeQNodes[i].params[2].v = parityStripeID;
        !           877:                        writeQNodes[i].params[3].v =
        !           878:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           879:                            0, 0, which_ru);
        !           880:                        if (lu_flag) {
        !           881:                                /* Initialize node to unlock the disk queue. */
        !           882:                                rf_InitNode(&unlockQNodes[i], rf_wait,
        !           883:                                    RF_FALSE, rf_DiskUnlockFunc,
        !           884:                                    rf_DiskUnlockUndoFunc,
        !           885:                                    rf_GenericWakeupFunc, 1, 1, 2, 0,
        !           886:                                    dag_h, "Unq", allocList);
        !           887:                                /* Physical disk addr desc. */
        !           888:                                unlockQNodes[i].params[0].p = pda;
        !           889:                                unlockQNodes[i].params[1].v =
        !           890:                                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           891:                                    0, lu_flag, which_ru);
        !           892:                        }
        !           893:                        pda = pda->next;
        !           894:                }
        !           895:        }
        !           896:        /*
        !           897:         * Step 4. Connect the nodes.
        !           898:         */
        !           899:
        !           900:        /* Connect header to block node. */
        !           901:        dag_h->succedents[0] = blockNode;
        !           902:
        !           903:        /* Connect block node to read old data nodes. */
        !           904:        RF_ASSERT(blockNode->numSuccedents ==
        !           905:            (numDataNodes + (numParityNodes * nfaults)));
        !           906:        for (i = 0; i < numDataNodes; i++) {
        !           907:                blockNode->succedents[i] = &readDataNodes[i];
        !           908:                RF_ASSERT(readDataNodes[i].numAntecedents == 1);
        !           909:                readDataNodes[i].antecedents[0] = blockNode;
        !           910:                readDataNodes[i].antType[0] = rf_control;
        !           911:        }
        !           912:
        !           913:        /* Connect block node to read old parity nodes. */
        !           914:        for (i = 0; i < numParityNodes; i++) {
        !           915:                blockNode->succedents[numDataNodes + i] = &readParityNodes[i];
        !           916:                RF_ASSERT(readParityNodes[i].numAntecedents == 1);
        !           917:                readParityNodes[i].antecedents[0] = blockNode;
        !           918:                readParityNodes[i].antType[0] = rf_control;
        !           919:        }
        !           920:
        !           921:        /* Connect block node to read old Q nodes. */
        !           922:        if (nfaults == 2) {
        !           923:                for (i = 0; i < numParityNodes; i++) {
        !           924:                        blockNode->succedents[numDataNodes + numParityNodes + i]
        !           925:                            = &readQNodes[i];
        !           926:                        RF_ASSERT(readQNodes[i].numAntecedents == 1);
        !           927:                        readQNodes[i].antecedents[0] = blockNode;
        !           928:                        readQNodes[i].antType[0] = rf_control;
        !           929:                }
        !           930:        }
        !           931:        /* Connect read old data nodes to xor nodes. */
        !           932:        for (i = 0; i < numDataNodes; i++) {
        !           933:                RF_ASSERT(readDataNodes[i].numSuccedents ==
        !           934:                    (nfaults * numParityNodes));
        !           935:                for (j = 0; j < numParityNodes; j++) {
        !           936:                        RF_ASSERT(xorNodes[j].numAntecedents ==
        !           937:                            numDataNodes + numParityNodes);
        !           938:                        readDataNodes[i].succedents[j] = &xorNodes[j];
        !           939:                        xorNodes[j].antecedents[i] = &readDataNodes[i];
        !           940:                        xorNodes[j].antType[i] = rf_trueData;
        !           941:                }
        !           942:        }
        !           943:
        !           944:        /* Connect read old data nodes to q nodes. */
        !           945:        if (nfaults == 2) {
        !           946:                for (i = 0; i < numDataNodes; i++) {
        !           947:                        for (j = 0; j < numParityNodes; j++) {
        !           948:                                RF_ASSERT(qNodes[j].numAntecedents ==
        !           949:                                    numDataNodes + numParityNodes);
        !           950:                                readDataNodes[i].succedents[numParityNodes + j]
        !           951:                                    = &qNodes[j];
        !           952:                                qNodes[j].antecedents[i] = &readDataNodes[i];
        !           953:                                qNodes[j].antType[i] = rf_trueData;
        !           954:                        }
        !           955:                }
        !           956:        }
        !           957:        /* Connect read old parity nodes to xor nodes. */
        !           958:        for (i = 0; i < numParityNodes; i++) {
        !           959:                RF_ASSERT(readParityNodes[i].numSuccedents == numParityNodes);
        !           960:                for (j = 0; j < numParityNodes; j++) {
        !           961:                        readParityNodes[i].succedents[j] = &xorNodes[j];
        !           962:                        xorNodes[j].antecedents[numDataNodes + i] =
        !           963:                            &readParityNodes[i];
        !           964:                        xorNodes[j].antType[numDataNodes + i] = rf_trueData;
        !           965:                }
        !           966:        }
        !           967:
        !           968:        /* Connect read old q nodes to q nodes. */
        !           969:        if (nfaults == 2) {
        !           970:                for (i = 0; i < numParityNodes; i++) {
        !           971:                        RF_ASSERT(readParityNodes[i].numSuccedents ==
        !           972:                            numParityNodes);
        !           973:                        for (j = 0; j < numParityNodes; j++) {
        !           974:                                readQNodes[i].succedents[j] = &qNodes[j];
        !           975:                                qNodes[j].antecedents[numDataNodes + i] =
        !           976:                                    &readQNodes[i];
        !           977:                                qNodes[j].antType[numDataNodes + i] =
        !           978:                                    rf_trueData;
        !           979:                        }
        !           980:                }
        !           981:        }
        !           982:        /* Connect xor nodes to commit node. */
        !           983:        RF_ASSERT(commitNode->numAntecedents == (nfaults * numParityNodes));
        !           984:        for (i = 0; i < numParityNodes; i++) {
        !           985:                RF_ASSERT(xorNodes[i].numSuccedents == 1);
        !           986:                xorNodes[i].succedents[0] = commitNode;
        !           987:                commitNode->antecedents[i] = &xorNodes[i];
        !           988:                commitNode->antType[i] = rf_control;
        !           989:        }
        !           990:
        !           991:        /* Connect q nodes to commit node. */
        !           992:        if (nfaults == 2) {
        !           993:                for (i = 0; i < numParityNodes; i++) {
        !           994:                        RF_ASSERT(qNodes[i].numSuccedents == 1);
        !           995:                        qNodes[i].succedents[0] = commitNode;
        !           996:                        commitNode->antecedents[i + numParityNodes] =
        !           997:                            &qNodes[i];
        !           998:                        commitNode->antType[i + numParityNodes] = rf_control;
        !           999:                }
        !          1000:        }
        !          1001:        /* Connect commit node to write nodes. */
        !          1002:        RF_ASSERT(commitNode->numSuccedents ==
        !          1003:            (numDataNodes + (nfaults * numParityNodes)));
        !          1004:        for (i = 0; i < numDataNodes; i++) {
        !          1005:                RF_ASSERT(writeDataNodes[i].numAntecedents == 1);
        !          1006:                commitNode->succedents[i] = &writeDataNodes[i];
        !          1007:                writeDataNodes[i].antecedents[0] = commitNode;
        !          1008:                writeDataNodes[i].antType[0] = rf_trueData;
        !          1009:        }
        !          1010:        for (i = 0; i < numParityNodes; i++) {
        !          1011:                RF_ASSERT(writeParityNodes[i].numAntecedents == 1);
        !          1012:                commitNode->succedents[i + numDataNodes] = &writeParityNodes[i];
        !          1013:                writeParityNodes[i].antecedents[0] = commitNode;
        !          1014:                writeParityNodes[i].antType[0] = rf_trueData;
        !          1015:        }
        !          1016:        if (nfaults == 2) {
        !          1017:                for (i = 0; i < numParityNodes; i++) {
        !          1018:                        RF_ASSERT(writeQNodes[i].numAntecedents == 1);
        !          1019:                        commitNode->succedents
        !          1020:                            [i + numDataNodes + numParityNodes] =
        !          1021:                            &writeQNodes[i];
        !          1022:                        writeQNodes[i].antecedents[0] = commitNode;
        !          1023:                        writeQNodes[i].antType[0] = rf_trueData;
        !          1024:                }
        !          1025:        }
        !          1026:        RF_ASSERT(termNode->numAntecedents ==
        !          1027:            (numDataNodes + (nfaults * numParityNodes)));
        !          1028:        RF_ASSERT(termNode->numSuccedents == 0);
        !          1029:        for (i = 0; i < numDataNodes; i++) {
        !          1030:                if (lu_flag) {
        !          1031:                        /* Connect write new data nodes to unlock nodes. */
        !          1032:                        RF_ASSERT(writeDataNodes[i].numSuccedents == 1);
        !          1033:                        RF_ASSERT(unlockDataNodes[i].numAntecedents == 1);
        !          1034:                        writeDataNodes[i].succedents[0] = &unlockDataNodes[i];
        !          1035:                        unlockDataNodes[i].antecedents[0] = &writeDataNodes[i];
        !          1036:                        unlockDataNodes[i].antType[0] = rf_control;
        !          1037:
        !          1038:                        /* Connect unlock nodes to term node. */
        !          1039:                        RF_ASSERT(unlockDataNodes[i].numSuccedents == 1);
        !          1040:                        unlockDataNodes[i].succedents[0] = termNode;
        !          1041:                        termNode->antecedents[i] = &unlockDataNodes[i];
        !          1042:                        termNode->antType[i] = rf_control;
        !          1043:                } else {
        !          1044:                        /* Connect write new data nodes to term node. */
        !          1045:                        RF_ASSERT(writeDataNodes[i].numSuccedents == 1);
        !          1046:                        RF_ASSERT(termNode->numAntecedents ==
        !          1047:                            (numDataNodes + (nfaults * numParityNodes)));
        !          1048:                        writeDataNodes[i].succedents[0] = termNode;
        !          1049:                        termNode->antecedents[i] = &writeDataNodes[i];
        !          1050:                        termNode->antType[i] = rf_control;
        !          1051:                }
        !          1052:        }
        !          1053:
        !          1054:        for (i = 0; i < numParityNodes; i++) {
        !          1055:                if (lu_flag) {
        !          1056:                        /* Connect write new parity nodes to unlock nodes. */
        !          1057:                        RF_ASSERT(writeParityNodes[i].numSuccedents == 1);
        !          1058:                        RF_ASSERT(unlockParityNodes[i].numAntecedents == 1);
        !          1059:                        writeParityNodes[i].succedents[0] =
        !          1060:                            &unlockParityNodes[i];
        !          1061:                        unlockParityNodes[i].antecedents[0] =
        !          1062:                            &writeParityNodes[i];
        !          1063:                        unlockParityNodes[i].antType[0] = rf_control;
        !          1064:
        !          1065:                        /* Connect unlock nodes to term node. */
        !          1066:                        RF_ASSERT(unlockParityNodes[i].numSuccedents == 1);
        !          1067:                        unlockParityNodes[i].succedents[0] = termNode;
        !          1068:                        termNode->antecedents[numDataNodes + i] =
        !          1069:                            &unlockParityNodes[i];
        !          1070:                        termNode->antType[numDataNodes + i] = rf_control;
        !          1071:                } else {
        !          1072:                        RF_ASSERT(writeParityNodes[i].numSuccedents == 1);
        !          1073:                        writeParityNodes[i].succedents[0] = termNode;
        !          1074:                        termNode->antecedents[numDataNodes + i] =
        !          1075:                            &writeParityNodes[i];
        !          1076:                        termNode->antType[numDataNodes + i] = rf_control;
        !          1077:                }
        !          1078:        }
        !          1079:
        !          1080:        if (nfaults == 2) {
        !          1081:                for (i = 0; i < numParityNodes; i++) {
        !          1082:                        if (lu_flag) {
        !          1083:                                /* Connect write new Q nodes to unlock nodes. */
        !          1084:                                RF_ASSERT(writeQNodes[i].numSuccedents == 1);
        !          1085:                                RF_ASSERT(unlockQNodes[i].numAntecedents == 1);
        !          1086:                                writeQNodes[i].succedents[0] = &unlockQNodes[i];
        !          1087:                                unlockQNodes[i].antecedents[0] =
        !          1088:                                    &writeQNodes[i];
        !          1089:                                unlockQNodes[i].antType[0] = rf_control;
        !          1090:
        !          1091:                                /* Connect unlock nodes to unblock node. */
        !          1092:                                RF_ASSERT(unlockQNodes[i].numSuccedents == 1);
        !          1093:                                unlockQNodes[i].succedents[0] = termNode;
        !          1094:                                termNode->antecedents
        !          1095:                                    [numDataNodes + numParityNodes + i] =
        !          1096:                                    &unlockQNodes[i];
        !          1097:                                termNode->antType
        !          1098:                                    [numDataNodes + numParityNodes + i] =
        !          1099:                                    rf_control;
        !          1100:                        } else {
        !          1101:                                RF_ASSERT(writeQNodes[i].numSuccedents == 1);
        !          1102:                                writeQNodes[i].succedents[0] = termNode;
        !          1103:                                termNode->antecedents
        !          1104:                                    [numDataNodes + numParityNodes + i] =
        !          1105:                                    &writeQNodes[i];
        !          1106:                                termNode->antType
        !          1107:                                    [numDataNodes + numParityNodes + i] =
        !          1108:                                    rf_control;
        !          1109:                        }
        !          1110:                }
        !          1111:        }
        !          1112: }
        !          1113:
        !          1114:
        !          1115: /*****************************************************************************
        !          1116:  * Create a write graph (fault-free or degraded) for RAID level 1.
        !          1117:  *
        !          1118:  * Hdr -> Commit -> Wpd -> Nil -> Trm
        !          1119:  *              -> Wsd ->
        !          1120:  *
        !          1121:  * The "Wpd" node writes data to the primary copy in the mirror pair.
        !          1122:  * The "Wsd" node writes data to the secondary copy in the mirror pair.
        !          1123:  *
        !          1124:  * Parameters: raidPtr   - description of the physical array
        !          1125:  *             asmap     - logical & physical addresses for this access
        !          1126:  *             bp        - buffer ptr (holds write data)
        !          1127:  *             flags     - general flags (e.g. disk locking)
        !          1128:  *             allocList - list of memory allocated in DAG creation
        !          1129:  *****************************************************************************/
        !          1130:
        !          1131: void
        !          1132: rf_CreateRaidOneWriteDAG(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !          1133:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !          1134:     RF_AllocListElem_t *allocList)
        !          1135: {
        !          1136:        RF_DagNode_t *unblockNode, *termNode, *commitNode;
        !          1137:        RF_DagNode_t *nodes, *wndNode, *wmirNode;
        !          1138:        int nWndNodes, nWmirNodes, i;
        !          1139:        RF_ReconUnitNum_t which_ru;
        !          1140:        RF_PhysDiskAddr_t *pda, *pdaP;
        !          1141:        RF_StripeNum_t parityStripeID;
        !          1142:
        !          1143:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !          1144:            asmap->raidAddress, &which_ru);
        !          1145:        if (rf_dagDebug) {
        !          1146:                printf("[Creating RAID level 1 write DAG]\n");
        !          1147:        }
        !          1148:        dag_h->creator = "RaidOneWriteDAG";
        !          1149:
        !          1150:        /* 2 implies access not SU aligned. */
        !          1151:        nWmirNodes = (asmap->parityInfo->next) ? 2 : 1;
        !          1152:        nWndNodes = (asmap->physInfo->next) ? 2 : 1;
        !          1153:
        !          1154:        /* Alloc the Wnd nodes and the Wmir node. */
        !          1155:        if (asmap->numDataFailed == 1)
        !          1156:                nWndNodes--;
        !          1157:        if (asmap->numParityFailed == 1)
        !          1158:                nWmirNodes--;
        !          1159:
        !          1160:        /*
        !          1161:         * Total number of nodes = nWndNodes + nWmirNodes
        !          1162:         * + (commit + unblock + terminator)
        !          1163:         */
        !          1164:        RF_CallocAndAdd(nodes, nWndNodes + nWmirNodes + 3, sizeof(RF_DagNode_t),
        !          1165:            (RF_DagNode_t *), allocList);
        !          1166:        i = 0;
        !          1167:        wndNode = &nodes[i];
        !          1168:        i += nWndNodes;
        !          1169:        wmirNode = &nodes[i];
        !          1170:        i += nWmirNodes;
        !          1171:        commitNode = &nodes[i];
        !          1172:        i += 1;
        !          1173:        unblockNode = &nodes[i];
        !          1174:        i += 1;
        !          1175:        termNode = &nodes[i];
        !          1176:        i += 1;
        !          1177:        RF_ASSERT(i == (nWndNodes + nWmirNodes + 3));
        !          1178:
        !          1179:        /* This dag can commit immediately. */
        !          1180:        dag_h->numCommitNodes = 1;
        !          1181:        dag_h->numCommits = 0;
        !          1182:        dag_h->numSuccedents = 1;
        !          1183:
        !          1184:        /* Initialize the commit, unblock, and term nodes. */
        !          1185:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !          1186:            rf_NullNodeUndoFunc, NULL, (nWndNodes + nWmirNodes), 0, 0, 0,
        !          1187:            dag_h, "Cmt", allocList);
        !          1188:        rf_InitNode(unblockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1189:            rf_NullNodeUndoFunc, NULL, 1, (nWndNodes + nWmirNodes), 0, 0,
        !          1190:            dag_h, "Nil", allocList);
        !          1191:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !          1192:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", allocList);
        !          1193:
        !          1194:        /* Initialize the wnd nodes. */
        !          1195:        if (nWndNodes > 0) {
        !          1196:                pda = asmap->physInfo;
        !          1197:                for (i = 0; i < nWndNodes; i++) {
        !          1198:                        rf_InitNode(&wndNode[i], rf_wait, RF_FALSE,
        !          1199:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          1200:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !          1201:                            "Wpd", allocList);
        !          1202:                        RF_ASSERT(pda != NULL);
        !          1203:                        wndNode[i].params[0].p = pda;
        !          1204:                        wndNode[i].params[1].p = pda->bufPtr;
        !          1205:                        wndNode[i].params[2].v = parityStripeID;
        !          1206:                        wndNode[i].params[3].v =
        !          1207:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1208:                            0, 0, which_ru);
        !          1209:                        pda = pda->next;
        !          1210:                }
        !          1211:                RF_ASSERT(pda == NULL);
        !          1212:        }
        !          1213:        /* Initialize the mirror nodes. */
        !          1214:        if (nWmirNodes > 0) {
        !          1215:                pda = asmap->physInfo;
        !          1216:                pdaP = asmap->parityInfo;
        !          1217:                for (i = 0; i < nWmirNodes; i++) {
        !          1218:                        rf_InitNode(&wmirNode[i], rf_wait, RF_FALSE,
        !          1219:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          1220:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !          1221:                            "Wsd", allocList);
        !          1222:                        RF_ASSERT(pda != NULL);
        !          1223:                        wmirNode[i].params[0].p = pdaP;
        !          1224:                        wmirNode[i].params[1].p = pda->bufPtr;
        !          1225:                        wmirNode[i].params[2].v = parityStripeID;
        !          1226:                        wmirNode[i].params[3].v =
        !          1227:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1228:                            0, 0, which_ru);
        !          1229:                        pda = pda->next;
        !          1230:                        pdaP = pdaP->next;
        !          1231:                }
        !          1232:                RF_ASSERT(pda == NULL);
        !          1233:                RF_ASSERT(pdaP == NULL);
        !          1234:        }
        !          1235:        /* Link the header node to the commit node. */
        !          1236:        RF_ASSERT(dag_h->numSuccedents == 1);
        !          1237:        RF_ASSERT(commitNode->numAntecedents == 0);
        !          1238:        dag_h->succedents[0] = commitNode;
        !          1239:
        !          1240:        /* Link the commit node to the write nodes. */
        !          1241:        RF_ASSERT(commitNode->numSuccedents == (nWndNodes + nWmirNodes));
        !          1242:        for (i = 0; i < nWndNodes; i++) {
        !          1243:                RF_ASSERT(wndNode[i].numAntecedents == 1);
        !          1244:                commitNode->succedents[i] = &wndNode[i];
        !          1245:                wndNode[i].antecedents[0] = commitNode;
        !          1246:                wndNode[i].antType[0] = rf_control;
        !          1247:        }
        !          1248:        for (i = 0; i < nWmirNodes; i++) {
        !          1249:                RF_ASSERT(wmirNode[i].numAntecedents == 1);
        !          1250:                commitNode->succedents[i + nWndNodes] = &wmirNode[i];
        !          1251:                wmirNode[i].antecedents[0] = commitNode;
        !          1252:                wmirNode[i].antType[0] = rf_control;
        !          1253:        }
        !          1254:
        !          1255:        /* Link the write nodes to the unblock node. */
        !          1256:        RF_ASSERT(unblockNode->numAntecedents == (nWndNodes + nWmirNodes));
        !          1257:        for (i = 0; i < nWndNodes; i++) {
        !          1258:                RF_ASSERT(wndNode[i].numSuccedents == 1);
        !          1259:                wndNode[i].succedents[0] = unblockNode;
        !          1260:                unblockNode->antecedents[i] = &wndNode[i];
        !          1261:                unblockNode->antType[i] = rf_control;
        !          1262:        }
        !          1263:        for (i = 0; i < nWmirNodes; i++) {
        !          1264:                RF_ASSERT(wmirNode[i].numSuccedents == 1);
        !          1265:                wmirNode[i].succedents[0] = unblockNode;
        !          1266:                unblockNode->antecedents[i + nWndNodes] = &wmirNode[i];
        !          1267:                unblockNode->antType[i + nWndNodes] = rf_control;
        !          1268:        }
        !          1269:
        !          1270:        /* Link the unblock node to the term node. */
        !          1271:        RF_ASSERT(unblockNode->numSuccedents == 1);
        !          1272:        RF_ASSERT(termNode->numAntecedents == 1);
        !          1273:        RF_ASSERT(termNode->numSuccedents == 0);
        !          1274:        unblockNode->succedents[0] = termNode;
        !          1275:        termNode->antecedents[0] = unblockNode;
        !          1276:        termNode->antType[0] = rf_control;
        !          1277: }
        !          1278:
        !          1279:
        !          1280:
        !          1281: /*
        !          1282:  * DAGs that have no commit points.
        !          1283:  *
        !          1284:  * The following DAGs are used in forward and backward error recovery
        !          1285:  * experiments.
        !          1286:  * They are identical to the DAGs above this comment with the exception that
        !          1287:  * the commit points have been removed.
        !          1288:  */
        !          1289:
        !          1290:
        !          1291: void
        !          1292: rf_CommonCreateLargeWriteDAGFwd(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !          1293:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !          1294:     RF_AllocListElem_t *allocList, int nfaults, int (*redFunc) (RF_DagNode_t *),
        !          1295:     int allowBufferRecycle)
        !          1296: {
        !          1297:        RF_DagNode_t *nodes, *wndNodes, *rodNodes, *xorNode, *wnpNode;
        !          1298:        RF_DagNode_t *wnqNode, *blockNode, *syncNode, *termNode;
        !          1299:        int nWndNodes, nRodNodes, i, nodeNum, asmNum;
        !          1300:        RF_AccessStripeMapHeader_t *new_asm_h[2];
        !          1301:        RF_StripeNum_t parityStripeID;
        !          1302:        char *sosBuffer, *eosBuffer;
        !          1303:        RF_ReconUnitNum_t which_ru;
        !          1304:        RF_RaidLayout_t *layoutPtr;
        !          1305:        RF_PhysDiskAddr_t *pda;
        !          1306:
        !          1307:        layoutPtr = &(raidPtr->Layout);
        !          1308:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !          1309:            asmap->raidAddress, &which_ru);
        !          1310:
        !          1311:        if (rf_dagDebug)
        !          1312:                printf("[Creating large-write DAG]\n");
        !          1313:        dag_h->creator = "LargeWriteDAGFwd";
        !          1314:
        !          1315:        dag_h->numCommitNodes = 0;
        !          1316:        dag_h->numCommits = 0;
        !          1317:        dag_h->numSuccedents = 1;
        !          1318:
        !          1319:        /* Alloc the nodes: Wnd, xor, commit, block, term, and  Wnp. */
        !          1320:        nWndNodes = asmap->numStripeUnitsAccessed;
        !          1321:        RF_CallocAndAdd(nodes, nWndNodes + 4 + nfaults, sizeof(RF_DagNode_t),
        !          1322:            (RF_DagNode_t *), allocList);
        !          1323:        i = 0;
        !          1324:        wndNodes = &nodes[i];
        !          1325:        i += nWndNodes;
        !          1326:        xorNode = &nodes[i];
        !          1327:        i += 1;
        !          1328:        wnpNode = &nodes[i];
        !          1329:        i += 1;
        !          1330:        blockNode = &nodes[i];
        !          1331:        i += 1;
        !          1332:        syncNode = &nodes[i];
        !          1333:        i += 1;
        !          1334:        termNode = &nodes[i];
        !          1335:        i += 1;
        !          1336:        if (nfaults == 2) {
        !          1337:                wnqNode = &nodes[i];
        !          1338:                i += 1;
        !          1339:        } else {
        !          1340:                wnqNode = NULL;
        !          1341:        }
        !          1342:        rf_MapUnaccessedPortionOfStripe(raidPtr, layoutPtr, asmap, dag_h,
        !          1343:            new_asm_h, &nRodNodes, &sosBuffer, &eosBuffer, allocList);
        !          1344:        if (nRodNodes > 0) {
        !          1345:                RF_CallocAndAdd(rodNodes, nRodNodes, sizeof(RF_DagNode_t),
        !          1346:                    (RF_DagNode_t *), allocList);
        !          1347:        } else {
        !          1348:                rodNodes = NULL;
        !          1349:        }
        !          1350:
        !          1351:        /* Begin node initialization. */
        !          1352:        if (nRodNodes > 0) {
        !          1353:                rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1354:                    rf_NullNodeUndoFunc, NULL, nRodNodes, 0, 0, 0, dag_h,
        !          1355:                    "Nil", allocList);
        !          1356:                rf_InitNode(syncNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1357:                    rf_NullNodeUndoFunc, NULL, nWndNodes + 1, nRodNodes, 0, 0,
        !          1358:                    dag_h, "Nil", allocList);
        !          1359:        } else {
        !          1360:                rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1361:                    rf_NullNodeUndoFunc, NULL, 1, 0, 0, 0, dag_h, "Nil",
        !          1362:                    allocList);
        !          1363:                rf_InitNode(syncNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1364:                    rf_NullNodeUndoFunc, NULL, nWndNodes + 1, 1, 0, 0, dag_h,
        !          1365:                    "Nil", allocList);
        !          1366:        }
        !          1367:
        !          1368:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !          1369:            rf_TerminateUndoFunc, NULL, 0, nWndNodes + nfaults, 0, 0,
        !          1370:            dag_h, "Trm", allocList);
        !          1371:
        !          1372:        /* Initialize the Rod nodes. */
        !          1373:        for (nodeNum = asmNum = 0; asmNum < 2; asmNum++) {
        !          1374:                if (new_asm_h[asmNum]) {
        !          1375:                        pda = new_asm_h[asmNum]->stripeMap->physInfo;
        !          1376:                        while (pda) {
        !          1377:                                rf_InitNode(&rodNodes[nodeNum], rf_wait,
        !          1378:                                    RF_FALSE, rf_DiskReadFunc,
        !          1379:                                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !          1380:                                    1, 1, 4, 0, dag_h, "Rod", allocList);
        !          1381:                                rodNodes[nodeNum].params[0].p = pda;
        !          1382:                                rodNodes[nodeNum].params[1].p = pda->bufPtr;
        !          1383:                                rodNodes[nodeNum].params[2].v = parityStripeID;
        !          1384:                                rodNodes[nodeNum].params[3].v =
        !          1385:                                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1386:                                    0, 0, which_ru);
        !          1387:                                nodeNum++;
        !          1388:                                pda = pda->next;
        !          1389:                        }
        !          1390:                }
        !          1391:        }
        !          1392:        RF_ASSERT(nodeNum == nRodNodes);
        !          1393:
        !          1394:        /* Initialize the wnd nodes. */
        !          1395:        pda = asmap->physInfo;
        !          1396:        for (i = 0; i < nWndNodes; i++) {
        !          1397:                rf_InitNode(&wndNodes[i], rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !          1398:                    rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !          1399:                    dag_h, "Wnd", allocList);
        !          1400:                RF_ASSERT(pda != NULL);
        !          1401:                wndNodes[i].params[0].p = pda;
        !          1402:                wndNodes[i].params[1].p = pda->bufPtr;
        !          1403:                wndNodes[i].params[2].v = parityStripeID;
        !          1404:                wndNodes[i].params[3].v =
        !          1405:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !          1406:                pda = pda->next;
        !          1407:        }
        !          1408:
        !          1409:        /* Initialize the redundancy node. */
        !          1410:        rf_InitNode(xorNode, rf_wait, RF_FALSE, redFunc, rf_NullNodeUndoFunc,
        !          1411:            NULL, 1, nfaults, 2 * (nWndNodes + nRodNodes) + 1, nfaults, dag_h,
        !          1412:            "Xr ", allocList);
        !          1413:        xorNode->flags |= RF_DAGNODE_FLAG_YIELD;
        !          1414:        for (i = 0; i < nWndNodes; i++) {
        !          1415:                xorNode->params[2 * i + 0] =
        !          1416:                    wndNodes[i].params[0];      /* pda */
        !          1417:                xorNode->params[2 * i + 1] =
        !          1418:                    wndNodes[i].params[1];      /* buf ptr */
        !          1419:        }
        !          1420:        for (i = 0; i < nRodNodes; i++) {
        !          1421:                xorNode->params[2 * (nWndNodes + i) + 0] =
        !          1422:                    rodNodes[i].params[0];      /* pda */
        !          1423:                xorNode->params[2 * (nWndNodes + i) + 1] =
        !          1424:                    rodNodes[i].params[1];      /* buf ptr */
        !          1425:        }
        !          1426:        /* Xor node needs to get at RAID information. */
        !          1427:        xorNode->params[2 * (nWndNodes + nRodNodes)].p = raidPtr;
        !          1428:
        !          1429:        /*
        !          1430:         * Look for an Rod node that reads a complete SU. If none, alloc a
        !          1431:         * buffer to receive the parity info. Note that we can't use a new
        !          1432:         * data buffer because it will not have gotten written when the xor
        !          1433:         * occurs.
        !          1434:         */
        !          1435:        if (allowBufferRecycle) {
        !          1436:                for (i = 0; i < nRodNodes; i++)
        !          1437:                        if (((RF_PhysDiskAddr_t *) rodNodes[i].params[0].p)
        !          1438:                            ->numSector == raidPtr->Layout.sectorsPerStripeUnit)
        !          1439:                                break;
        !          1440:        }
        !          1441:        if ((!allowBufferRecycle) || (i == nRodNodes)) {
        !          1442:                RF_CallocAndAdd(xorNode->results[0], 1,
        !          1443:                    rf_RaidAddressToByte(raidPtr,
        !          1444:                    raidPtr->Layout.sectorsPerStripeUnit),
        !          1445:                    (void *), allocList);
        !          1446:        } else
        !          1447:                xorNode->results[0] = rodNodes[i].params[1].p;
        !          1448:
        !          1449:        /* Initialize the Wnp node. */
        !          1450:        rf_InitNode(wnpNode, rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !          1451:            rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !          1452:            dag_h, "Wnp", allocList);
        !          1453:        wnpNode->params[0].p = asmap->parityInfo;
        !          1454:        wnpNode->params[1].p = xorNode->results[0];
        !          1455:        wnpNode->params[2].v = parityStripeID;
        !          1456:        wnpNode->params[3].v =
        !          1457:            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !          1458:        /* parityInfo must describe entire parity unit. */
        !          1459:        RF_ASSERT(asmap->parityInfo->next == NULL);
        !          1460:
        !          1461:        if (nfaults == 2) {
        !          1462:                /*
        !          1463:                 * Never try to recycle a buffer for the Q calcuation in
        !          1464:                 * addition to the parity. This would cause two buffers to
        !          1465:                 * get smashed during the P and Q calculation, guaranteeing
        !          1466:                 * one would be wrong.
        !          1467:                 */
        !          1468:                RF_CallocAndAdd(xorNode->results[1], 1,
        !          1469:                    rf_RaidAddressToByte(raidPtr,
        !          1470:                    raidPtr->Layout.sectorsPerStripeUnit),
        !          1471:                    (void *), allocList);
        !          1472:                rf_InitNode(wnqNode, rf_wait, RF_FALSE, rf_DiskWriteFunc,
        !          1473:                    rf_DiskWriteUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !          1474:                    dag_h, "Wnq", allocList);
        !          1475:                wnqNode->params[0].p = asmap->qInfo;
        !          1476:                wnqNode->params[1].p = xorNode->results[1];
        !          1477:                wnqNode->params[2].v = parityStripeID;
        !          1478:                wnqNode->params[3].v =
        !          1479:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !          1480:                /* parityInfo must describe entire parity unit. */
        !          1481:                RF_ASSERT(asmap->parityInfo->next == NULL);
        !          1482:        }
        !          1483:
        !          1484:        /* Connect nodes to form graph. */
        !          1485:
        !          1486:        /* Connect dag header to block node. */
        !          1487:        RF_ASSERT(blockNode->numAntecedents == 0);
        !          1488:        dag_h->succedents[0] = blockNode;
        !          1489:
        !          1490:        if (nRodNodes > 0) {
        !          1491:                /* Connect the block node to the Rod nodes. */
        !          1492:                RF_ASSERT(blockNode->numSuccedents == nRodNodes);
        !          1493:                RF_ASSERT(syncNode->numAntecedents == nRodNodes);
        !          1494:                for (i = 0; i < nRodNodes; i++) {
        !          1495:                        RF_ASSERT(rodNodes[i].numAntecedents == 1);
        !          1496:                        blockNode->succedents[i] = &rodNodes[i];
        !          1497:                        rodNodes[i].antecedents[0] = blockNode;
        !          1498:                        rodNodes[i].antType[0] = rf_control;
        !          1499:
        !          1500:                        /* Connect the Rod nodes to the Nil node. */
        !          1501:                        RF_ASSERT(rodNodes[i].numSuccedents == 1);
        !          1502:                        rodNodes[i].succedents[0] = syncNode;
        !          1503:                        syncNode->antecedents[i] = &rodNodes[i];
        !          1504:                        syncNode->antType[i] = rf_trueData;
        !          1505:                }
        !          1506:        } else {
        !          1507:                /* Connect the block node to the Nil node. */
        !          1508:                RF_ASSERT(blockNode->numSuccedents == 1);
        !          1509:                RF_ASSERT(syncNode->numAntecedents == 1);
        !          1510:                blockNode->succedents[0] = syncNode;
        !          1511:                syncNode->antecedents[0] = blockNode;
        !          1512:                syncNode->antType[0] = rf_control;
        !          1513:        }
        !          1514:
        !          1515:        /* Connect the sync node to the Wnd nodes. */
        !          1516:        RF_ASSERT(syncNode->numSuccedents == (1 + nWndNodes));
        !          1517:        for (i = 0; i < nWndNodes; i++) {
        !          1518:                RF_ASSERT(wndNodes->numAntecedents == 1);
        !          1519:                syncNode->succedents[i] = &wndNodes[i];
        !          1520:                wndNodes[i].antecedents[0] = syncNode;
        !          1521:                wndNodes[i].antType[0] = rf_control;
        !          1522:        }
        !          1523:
        !          1524:        /* Connect the sync node to the Xor node. */
        !          1525:        RF_ASSERT(xorNode->numAntecedents == 1);
        !          1526:        syncNode->succedents[nWndNodes] = xorNode;
        !          1527:        xorNode->antecedents[0] = syncNode;
        !          1528:        xorNode->antType[0] = rf_control;
        !          1529:
        !          1530:        /* Connect the xor node to the write parity node. */
        !          1531:        RF_ASSERT(xorNode->numSuccedents == nfaults);
        !          1532:        RF_ASSERT(wnpNode->numAntecedents == 1);
        !          1533:        xorNode->succedents[0] = wnpNode;
        !          1534:        wnpNode->antecedents[0] = xorNode;
        !          1535:        wnpNode->antType[0] = rf_trueData;
        !          1536:        if (nfaults == 2) {
        !          1537:                RF_ASSERT(wnqNode->numAntecedents == 1);
        !          1538:                xorNode->succedents[1] = wnqNode;
        !          1539:                wnqNode->antecedents[0] = xorNode;
        !          1540:                wnqNode->antType[0] = rf_trueData;
        !          1541:        }
        !          1542:        /* Connect the write nodes to the term node. */
        !          1543:        RF_ASSERT(termNode->numAntecedents == nWndNodes + nfaults);
        !          1544:        RF_ASSERT(termNode->numSuccedents == 0);
        !          1545:        for (i = 0; i < nWndNodes; i++) {
        !          1546:                RF_ASSERT(wndNodes->numSuccedents == 1);
        !          1547:                wndNodes[i].succedents[0] = termNode;
        !          1548:                termNode->antecedents[i] = &wndNodes[i];
        !          1549:                termNode->antType[i] = rf_control;
        !          1550:        }
        !          1551:        RF_ASSERT(wnpNode->numSuccedents == 1);
        !          1552:        wnpNode->succedents[0] = termNode;
        !          1553:        termNode->antecedents[nWndNodes] = wnpNode;
        !          1554:        termNode->antType[nWndNodes] = rf_control;
        !          1555:        if (nfaults == 2) {
        !          1556:                RF_ASSERT(wnqNode->numSuccedents == 1);
        !          1557:                wnqNode->succedents[0] = termNode;
        !          1558:                termNode->antecedents[nWndNodes + 1] = wnqNode;
        !          1559:                termNode->antType[nWndNodes + 1] = rf_control;
        !          1560:        }
        !          1561: }
        !          1562:
        !          1563:
        !          1564: /*****************************************************************************
        !          1565:  *
        !          1566:  * Create a DAG to perform a small-write operation (either raid 5 or pq),
        !          1567:  * which is as follows:
        !          1568:  *
        !          1569:  * Hdr -> Nil -> Rop - Xor - Wnp [Unp] -- Trm
        !          1570:  *            \- Rod X- Wnd [Und] -------/
        !          1571:  *           [\- Rod X- Wnd [Und] ------/]
        !          1572:  *           [\- Roq - Q --> Wnq [Unq]-/]
        !          1573:  *
        !          1574:  * Rop = read old parity
        !          1575:  * Rod = read old data
        !          1576:  * Roq = read old "q"
        !          1577:  * Cmt = commit node
        !          1578:  * Und = unlock data disk
        !          1579:  * Unp = unlock parity disk
        !          1580:  * Unq = unlock q disk
        !          1581:  * Wnp = write new parity
        !          1582:  * Wnd = write new data
        !          1583:  * Wnq = write new "q"
        !          1584:  * [ ] denotes optional segments in the graph.
        !          1585:  *
        !          1586:  * Parameters: raidPtr   - description of the physical array
        !          1587:  *             asmap     - logical & physical addresses for this access
        !          1588:  *             bp        - buffer ptr (holds write data)
        !          1589:  *             flags     - general flags (e.g. disk locking)
        !          1590:  *             allocList - list of memory allocated in DAG creation
        !          1591:  *             pfuncs    - list of parity generating functions
        !          1592:  *             qfuncs    - list of q generating functions
        !          1593:  *
        !          1594:  * A null qfuncs indicates single fault tolerant.
        !          1595:  *****************************************************************************/
        !          1596:
        !          1597: void
        !          1598: rf_CommonCreateSmallWriteDAGFwd(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !          1599:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !          1600:     RF_AllocListElem_t *allocList, RF_RedFuncs_t *pfuncs, RF_RedFuncs_t *qfuncs)
        !          1601: {
        !          1602:        RF_DagNode_t *readDataNodes, *readParityNodes, *readQNodes, *termNode;
        !          1603:        RF_DagNode_t *unlockDataNodes, *unlockParityNodes, *unlockQNodes;
        !          1604:        RF_DagNode_t *xorNodes, *qNodes, *blockNode, *nodes;
        !          1605:        RF_DagNode_t *writeDataNodes, *writeParityNodes, *writeQNodes;
        !          1606:        int i, j, nNodes, totalNumNodes, lu_flag;
        !          1607:        RF_ReconUnitNum_t which_ru;
        !          1608:        int (*func) (RF_DagNode_t *);
        !          1609:        int (*undoFunc) (RF_DagNode_t *);
        !          1610:        int (*qfunc) (RF_DagNode_t *);
        !          1611:        int numDataNodes, numParityNodes;
        !          1612:        RF_StripeNum_t parityStripeID;
        !          1613:        RF_PhysDiskAddr_t *pda;
        !          1614:        char *name, *qname;
        !          1615:        long nfaults;
        !          1616:
        !          1617:        nfaults = qfuncs ? 2 : 1;
        !          1618:        lu_flag = (rf_enableAtomicRMW) ? 1 : 0; /* Lock/unlock flag. */
        !          1619:
        !          1620:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !          1621:            asmap->raidAddress, &which_ru);
        !          1622:        pda = asmap->physInfo;
        !          1623:        numDataNodes = asmap->numStripeUnitsAccessed;
        !          1624:        numParityNodes = (asmap->parityInfo->next) ? 2 : 1;
        !          1625:
        !          1626:        if (rf_dagDebug)
        !          1627:                printf("[Creating small-write DAG]\n");
        !          1628:        RF_ASSERT(numDataNodes > 0);
        !          1629:        dag_h->creator = "SmallWriteDAGFwd";
        !          1630:
        !          1631:        dag_h->numCommitNodes = 0;
        !          1632:        dag_h->numCommits = 0;
        !          1633:        dag_h->numSuccedents = 1;
        !          1634:
        !          1635:        qfunc = NULL;
        !          1636:        qname = NULL;
        !          1637:
        !          1638:        /*
        !          1639:         * DAG creation occurs in four steps:
        !          1640:         * 1. Count the number of nodes in the DAG.
        !          1641:         * 2. Create the nodes.
        !          1642:         * 3. Initialize the nodes.
        !          1643:         * 4. Connect the nodes.
        !          1644:         */
        !          1645:
        !          1646:        /* Step 1. Compute number of nodes in the graph. */
        !          1647:
        !          1648:        /*
        !          1649:         * Number of nodes: a read and write for each data unit, a redundancy
        !          1650:         * computation node for each parity node (nfaults * nparity), a read
        !          1651:         * and write for each parity unit, a block node, a terminate node if
        !          1652:         * atomic RMW, an unlock node for each data/redundancy unit.
        !          1653:         */
        !          1654:        totalNumNodes = (2 * numDataNodes) + (nfaults * numParityNodes)
        !          1655:            + (nfaults * 2 * numParityNodes) + 2;
        !          1656:        if (lu_flag)
        !          1657:                totalNumNodes += (numDataNodes + (nfaults * numParityNodes));
        !          1658:
        !          1659:
        !          1660:        /* Step 2. Create the nodes. */
        !          1661:        RF_CallocAndAdd(nodes, totalNumNodes, sizeof(RF_DagNode_t),
        !          1662:            (RF_DagNode_t *), allocList);
        !          1663:        i = 0;
        !          1664:        blockNode = &nodes[i];
        !          1665:        i += 1;
        !          1666:        readDataNodes = &nodes[i];
        !          1667:        i += numDataNodes;
        !          1668:        readParityNodes = &nodes[i];
        !          1669:        i += numParityNodes;
        !          1670:        writeDataNodes = &nodes[i];
        !          1671:        i += numDataNodes;
        !          1672:        writeParityNodes = &nodes[i];
        !          1673:        i += numParityNodes;
        !          1674:        xorNodes = &nodes[i];
        !          1675:        i += numParityNodes;
        !          1676:        termNode = &nodes[i];
        !          1677:        i += 1;
        !          1678:        if (lu_flag) {
        !          1679:                unlockDataNodes = &nodes[i];
        !          1680:                i += numDataNodes;
        !          1681:                unlockParityNodes = &nodes[i];
        !          1682:                i += numParityNodes;
        !          1683:        } else {
        !          1684:                unlockDataNodes = unlockParityNodes = NULL;
        !          1685:        }
        !          1686:        if (nfaults == 2) {
        !          1687:                readQNodes = &nodes[i];
        !          1688:                i += numParityNodes;
        !          1689:                writeQNodes = &nodes[i];
        !          1690:                i += numParityNodes;
        !          1691:                qNodes = &nodes[i];
        !          1692:                i += numParityNodes;
        !          1693:                if (lu_flag) {
        !          1694:                        unlockQNodes = &nodes[i];
        !          1695:                        i += numParityNodes;
        !          1696:                } else {
        !          1697:                        unlockQNodes = NULL;
        !          1698:                }
        !          1699:        } else {
        !          1700:                readQNodes = writeQNodes = qNodes = unlockQNodes = NULL;
        !          1701:        }
        !          1702:        RF_ASSERT(i == totalNumNodes);
        !          1703:
        !          1704:        /* Step 3. Initialize the nodes. */
        !          1705:        /* Initialize block node (Nil). */
        !          1706:        nNodes = numDataNodes + (nfaults * numParityNodes);
        !          1707:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1708:            rf_NullNodeUndoFunc, NULL, nNodes, 0, 0, 0, dag_h,
        !          1709:            "Nil", allocList);
        !          1710:
        !          1711:        /* Initialize terminate node (Trm). */
        !          1712:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !          1713:            rf_TerminateUndoFunc, NULL, 0, nNodes, 0, 0, dag_h,
        !          1714:            "Trm", allocList);
        !          1715:
        !          1716:        /* Initialize nodes which read old data (Rod). */
        !          1717:        for (i = 0; i < numDataNodes; i++) {
        !          1718:                rf_InitNode(&readDataNodes[i], rf_wait, RF_FALSE,
        !          1719:                    rf_DiskReadFunc, rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !          1720:                    (numParityNodes * nfaults) + 1, 1, 4, 0, dag_h,
        !          1721:                    "Rod", allocList);
        !          1722:                RF_ASSERT(pda != NULL);
        !          1723:                /* Physical disk addr desc. */
        !          1724:                readDataNodes[i].params[0].p = pda;
        !          1725:                /* Buffer to hold old data. */
        !          1726:                readDataNodes[i].params[1].p = rf_AllocBuffer(raidPtr, dag_h,
        !          1727:                    pda, allocList);
        !          1728:                readDataNodes[i].params[2].v = parityStripeID;
        !          1729:                readDataNodes[i].params[3].v =
        !          1730:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1731:                    lu_flag, 0, which_ru);
        !          1732:                pda = pda->next;
        !          1733:                for (j = 0; j < readDataNodes[i].numSuccedents; j++)
        !          1734:                        readDataNodes[i].propList[j] = NULL;
        !          1735:        }
        !          1736:
        !          1737:        /* Initialize nodes which read old parity (Rop). */
        !          1738:        pda = asmap->parityInfo;
        !          1739:        i = 0;
        !          1740:        for (i = 0; i < numParityNodes; i++) {
        !          1741:                RF_ASSERT(pda != NULL);
        !          1742:                rf_InitNode(&readParityNodes[i], rf_wait, RF_FALSE,
        !          1743:                    rf_DiskReadFunc, rf_DiskReadUndoFunc, rf_GenericWakeupFunc,
        !          1744:                    numParityNodes, 1, 4, 0, dag_h, "Rop", allocList);
        !          1745:                readParityNodes[i].params[0].p = pda;
        !          1746:                /* Buffer to hold old parity. */
        !          1747:                readParityNodes[i].params[1].p = rf_AllocBuffer(raidPtr,
        !          1748:                    dag_h, pda, allocList);
        !          1749:                readParityNodes[i].params[2].v = parityStripeID;
        !          1750:                readParityNodes[i].params[3].v =
        !          1751:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1752:                    lu_flag, 0, which_ru);
        !          1753:                for (j = 0; j < readParityNodes[i].numSuccedents; j++)
        !          1754:                        readParityNodes[i].propList[0] = NULL;
        !          1755:                pda = pda->next;
        !          1756:        }
        !          1757:
        !          1758:        /* Initialize nodes which read old Q (Roq). */
        !          1759:        if (nfaults == 2) {
        !          1760:                pda = asmap->qInfo;
        !          1761:                for (i = 0; i < numParityNodes; i++) {
        !          1762:                        RF_ASSERT(pda != NULL);
        !          1763:                        rf_InitNode(&readQNodes[i], rf_wait, RF_FALSE,
        !          1764:                            rf_DiskReadFunc, rf_DiskReadUndoFunc,
        !          1765:                            rf_GenericWakeupFunc, numParityNodes, 1, 4, 0,
        !          1766:                            dag_h, "Roq", allocList);
        !          1767:                        readQNodes[i].params[0].p = pda;
        !          1768:                        /* Buffer to hold old Q. */
        !          1769:                        readQNodes[i].params[1].p = rf_AllocBuffer(raidPtr,
        !          1770:                            dag_h, pda, allocList);
        !          1771:                        readQNodes[i].params[2].v = parityStripeID;
        !          1772:                        readQNodes[i].params[3].v =
        !          1773:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1774:                            lu_flag, 0, which_ru);
        !          1775:                        for (j = 0; j < readQNodes[i].numSuccedents; j++)
        !          1776:                                readQNodes[i].propList[0] = NULL;
        !          1777:                        pda = pda->next;
        !          1778:                }
        !          1779:        }
        !          1780:        /* Initialize nodes which write new data (Wnd). */
        !          1781:        pda = asmap->physInfo;
        !          1782:        for (i = 0; i < numDataNodes; i++) {
        !          1783:                RF_ASSERT(pda != NULL);
        !          1784:                rf_InitNode(&writeDataNodes[i], rf_wait, RF_FALSE,
        !          1785:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          1786:                    rf_GenericWakeupFunc, 1, 1, 4, 0,
        !          1787:                    dag_h, "Wnd", allocList);
        !          1788:                /* Physical disk addr desc. */
        !          1789:                writeDataNodes[i].params[0].p = pda;
        !          1790:                /* Buffer holding new data to be written. */
        !          1791:                writeDataNodes[i].params[1].p = pda->bufPtr;
        !          1792:                writeDataNodes[i].params[2].v = parityStripeID;
        !          1793:                writeDataNodes[i].params[3].v =
        !          1794:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !          1795:
        !          1796:                if (lu_flag) {
        !          1797:                        /* Initialize node to unlock the disk queue. */
        !          1798:                        rf_InitNode(&unlockDataNodes[i], rf_wait, RF_FALSE,
        !          1799:                            rf_DiskUnlockFunc, rf_DiskUnlockUndoFunc,
        !          1800:                            rf_GenericWakeupFunc, 1, 1, 2, 0, dag_h,
        !          1801:                            "Und", allocList);
        !          1802:                        /* Physical disk addr desc. */
        !          1803:                        unlockDataNodes[i].params[0].p = pda;
        !          1804:                        unlockDataNodes[i].params[1].v =
        !          1805:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1806:                            0, lu_flag, which_ru);
        !          1807:                }
        !          1808:                pda = pda->next;
        !          1809:        }
        !          1810:
        !          1811:
        !          1812:        /* Initialize nodes which compute new parity and Q. */
        !          1813:        /*
        !          1814:         * Use the simple XOR func in the double-XOR case, and when
        !          1815:         * accessing only a portion of one stripe unit. The distinction
        !          1816:         * between the two is that the regular XOR func assumes that the
        !          1817:         * targbuf is a full SU in size, and examines the pda associated with
        !          1818:         * the buffer to decide where within the buffer to XOR the data,
        !          1819:         * whereas the simple XOR func just XORs the data into the start of
        !          1820:         * the buffer.
        !          1821:         */
        !          1822:        if ((numParityNodes == 2) || ((numDataNodes == 1) &&
        !          1823:            (asmap->totalSectorsAccessed <
        !          1824:             raidPtr->Layout.sectorsPerStripeUnit))) {
        !          1825:                func = pfuncs->simple;
        !          1826:                undoFunc = rf_NullNodeUndoFunc;
        !          1827:                name = pfuncs->SimpleName;
        !          1828:                if (qfuncs) {
        !          1829:                        qfunc = qfuncs->simple;
        !          1830:                        qname = qfuncs->SimpleName;
        !          1831:                }
        !          1832:        } else {
        !          1833:                func = pfuncs->regular;
        !          1834:                undoFunc = rf_NullNodeUndoFunc;
        !          1835:                name = pfuncs->RegularName;
        !          1836:                if (qfuncs) {
        !          1837:                        qfunc = qfuncs->regular;
        !          1838:                        qname = qfuncs->RegularName;
        !          1839:                }
        !          1840:        }
        !          1841:        /*
        !          1842:         * Initialize the xor nodes: params are {pda,buf} from {Rod,Wnd,Rop}
        !          1843:         * nodes, and raidPtr.
        !          1844:         */
        !          1845:        if (numParityNodes == 2) {      /* Double-xor case. */
        !          1846:                for (i = 0; i < numParityNodes; i++) {
        !          1847:                        /* No wakeup func for xor. */
        !          1848:                        rf_InitNode(&xorNodes[i], rf_wait, RF_FALSE, func,
        !          1849:                            undoFunc, NULL, numParityNodes, numParityNodes +
        !          1850:                            numDataNodes, 7, 1, dag_h, name, allocList);
        !          1851:                        xorNodes[i].flags |= RF_DAGNODE_FLAG_YIELD;
        !          1852:                        xorNodes[i].params[0] = readDataNodes[i].params[0];
        !          1853:                        xorNodes[i].params[1] = readDataNodes[i].params[1];
        !          1854:                        xorNodes[i].params[2] = readParityNodes[i].params[0];
        !          1855:                        xorNodes[i].params[3] = readParityNodes[i].params[1];
        !          1856:                        xorNodes[i].params[4] = writeDataNodes[i].params[0];
        !          1857:                        xorNodes[i].params[5] = writeDataNodes[i].params[1];
        !          1858:                        xorNodes[i].params[6].p = raidPtr;
        !          1859:                        /* Use old parity buf as target buf. */
        !          1860:                        xorNodes[i].results[0] = readParityNodes[i].params[1].p;
        !          1861:                        if (nfaults == 2) {
        !          1862:                                /* No wakeup func for xor. */
        !          1863:                                rf_InitNode(&qNodes[i], rf_wait, RF_FALSE,
        !          1864:                                    qfunc, undoFunc, NULL, numParityNodes,
        !          1865:                                    numParityNodes + numDataNodes, 7, 1,
        !          1866:                                    dag_h, qname, allocList);
        !          1867:                                qNodes[i].params[0] =
        !          1868:                                    readDataNodes[i].params[0];
        !          1869:                                qNodes[i].params[1] =
        !          1870:                                    readDataNodes[i].params[1];
        !          1871:                                qNodes[i].params[2] = readQNodes[i].params[0];
        !          1872:                                qNodes[i].params[3] = readQNodes[i].params[1];
        !          1873:                                qNodes[i].params[4] =
        !          1874:                                    writeDataNodes[i].params[0];
        !          1875:                                qNodes[i].params[5] =
        !          1876:                                    writeDataNodes[i].params[1];
        !          1877:                                qNodes[i].params[6].p = raidPtr;
        !          1878:                                /* Use old Q buf as target buf. */
        !          1879:                                qNodes[i].results[0] =
        !          1880:                                    readQNodes[i].params[1].p;
        !          1881:                        }
        !          1882:                }
        !          1883:        } else {
        !          1884:                /* There is only one xor node in this case. */
        !          1885:                rf_InitNode(&xorNodes[0], rf_wait, RF_FALSE, func, undoFunc,
        !          1886:                    NULL, numParityNodes, numParityNodes + numDataNodes,
        !          1887:                    (2 * (numDataNodes + numDataNodes + 1) + 1), 1, dag_h,
        !          1888:                    name, allocList);
        !          1889:                xorNodes[0].flags |= RF_DAGNODE_FLAG_YIELD;
        !          1890:                for (i = 0; i < numDataNodes + 1; i++) {
        !          1891:                        /* Set up params related to Rod and Rop nodes. */
        !          1892:                        xorNodes[0].params[2 * i + 0] =
        !          1893:                            readDataNodes[i].params[0]; /* pda */
        !          1894:                        xorNodes[0].params[2 * i + 1] =
        !          1895:                            readDataNodes[i].params[1]; /* buffer pointer */
        !          1896:                }
        !          1897:                for (i = 0; i < numDataNodes; i++) {
        !          1898:                        /* Set up params related to Wnd and Wnp nodes. */
        !          1899:                        xorNodes[0].params[2 * (numDataNodes + 1 + i) + 0] =
        !          1900:                            writeDataNodes[i].params[0]; /* pda */
        !          1901:                        xorNodes[0].params[2 * (numDataNodes + 1 + i) + 1] =
        !          1902:                            writeDataNodes[i].params[1]; /* buffer pointer */
        !          1903:                }
        !          1904:                xorNodes[0].params[2 * (numDataNodes + numDataNodes + 1)].p =
        !          1905:                    raidPtr;    /* xor node needs to get at RAID information */
        !          1906:                xorNodes[0].results[0] = readParityNodes[0].params[1].p;
        !          1907:                if (nfaults == 2) {
        !          1908:                        rf_InitNode(&qNodes[0], rf_wait, RF_FALSE, qfunc,
        !          1909:                            undoFunc, NULL, numParityNodes,
        !          1910:                            numParityNodes + numDataNodes,
        !          1911:                            (2 * (numDataNodes + numDataNodes + 1) + 1),
        !          1912:                            1, dag_h, qname, allocList);
        !          1913:                        for (i = 0; i < numDataNodes; i++) {
        !          1914:                                /* Set up params related to Rod. */
        !          1915:                                /* pda */
        !          1916:                                qNodes[0].params[2 * i + 0] =
        !          1917:                                    readDataNodes[i].params[0];
        !          1918:                                /* buffer pointer */
        !          1919:                                qNodes[0].params[2 * i + 1] =
        !          1920:                                    readDataNodes[i].params[1];
        !          1921:                        }
        !          1922:                        /* And read old q. */
        !          1923:                        qNodes[0].params[2 * numDataNodes + 0] =
        !          1924:                            readQNodes[0].params[0];    /* pda */
        !          1925:                        qNodes[0].params[2 * numDataNodes + 1] =
        !          1926:                            readQNodes[0].params[1];    /* buffer pointer */
        !          1927:                        for (i = 0; i < numDataNodes; i++) {
        !          1928:                                /* Set up params related to Wnd nodes. */
        !          1929:                                /* pda */
        !          1930:                                qNodes[0].params
        !          1931:                                    [2 * (numDataNodes + 1 + i) + 0] =
        !          1932:                                    writeDataNodes[i].params[0];
        !          1933:                                /* buffer pointer */
        !          1934:                                qNodes[0].params
        !          1935:                                    [2 * (numDataNodes + 1 + i) + 1] =
        !          1936:                                    writeDataNodes[i].params[1];
        !          1937:                        }
        !          1938:                        /* Xor node needs to get at RAID information. */
        !          1939:                        qNodes[0].params
        !          1940:                            [2 * (numDataNodes + numDataNodes + 1)].p =
        !          1941:                            raidPtr;
        !          1942:                        qNodes[0].results[0] = readQNodes[0].params[1].p;
        !          1943:                }
        !          1944:        }
        !          1945:
        !          1946:        /* Initialize nodes which write new parity (Wnp). */
        !          1947:        pda = asmap->parityInfo;
        !          1948:        for (i = 0; i < numParityNodes; i++) {
        !          1949:                rf_InitNode(&writeParityNodes[i], rf_wait, RF_FALSE,
        !          1950:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          1951:                    rf_GenericWakeupFunc, 1, numParityNodes,
        !          1952:                    4, 0, dag_h, "Wnp", allocList);
        !          1953:                RF_ASSERT(pda != NULL);
        !          1954:                /* Param 1 (bufPtr) filled in by xor node. */
        !          1955:                writeParityNodes[i].params[0].p = pda;
        !          1956:                /* Buffer pointer for parity write operation. */
        !          1957:                writeParityNodes[i].params[1].p = xorNodes[i].results[0];
        !          1958:                writeParityNodes[i].params[2].v = parityStripeID;
        !          1959:                writeParityNodes[i].params[3].v =
        !          1960:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !          1961:
        !          1962:                if (lu_flag) {
        !          1963:                        /* Initialize node to unlock the disk queue. */
        !          1964:                        rf_InitNode(&unlockParityNodes[i], rf_wait, RF_FALSE,
        !          1965:                            rf_DiskUnlockFunc, rf_DiskUnlockUndoFunc,
        !          1966:                            rf_GenericWakeupFunc, 1, 1, 2, 0, dag_h,
        !          1967:                            "Unp", allocList);
        !          1968:                        unlockParityNodes[i].params[0].p =
        !          1969:                            pda;        /* Physical disk addr desc. */
        !          1970:                        unlockParityNodes[i].params[1].v =
        !          1971:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1972:                            0, lu_flag, which_ru);
        !          1973:                }
        !          1974:                pda = pda->next;
        !          1975:        }
        !          1976:
        !          1977:        /* Initialize nodes which write new Q (Wnq). */
        !          1978:        if (nfaults == 2) {
        !          1979:                pda = asmap->qInfo;
        !          1980:                for (i = 0; i < numParityNodes; i++) {
        !          1981:                        rf_InitNode(&writeQNodes[i], rf_wait, RF_FALSE,
        !          1982:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          1983:                            rf_GenericWakeupFunc, 1, numParityNodes,
        !          1984:                            4, 0, dag_h, "Wnq", allocList);
        !          1985:                        RF_ASSERT(pda != NULL);
        !          1986:                        /* Param 1 (bufPtr) filled in by xor node. */
        !          1987:                        writeQNodes[i].params[0].p = pda;
        !          1988:                        /* Buffer pointer for parity write operation. */
        !          1989:                        writeQNodes[i].params[1].p = qNodes[i].results[0];
        !          1990:                        writeQNodes[i].params[2].v = parityStripeID;
        !          1991:                        writeQNodes[i].params[3].v =
        !          1992:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          1993:                            0, 0, which_ru);
        !          1994:
        !          1995:                        if (lu_flag) {
        !          1996:                                /* Initialize node to unlock the disk queue. */
        !          1997:                                rf_InitNode(&unlockQNodes[i], rf_wait,
        !          1998:                                    RF_FALSE, rf_DiskUnlockFunc,
        !          1999:                                    rf_DiskUnlockUndoFunc,
        !          2000:                                    rf_GenericWakeupFunc, 1, 1, 2, 0,
        !          2001:                                    dag_h, "Unq", allocList);
        !          2002:                                /* Physical disk addr desc. */
        !          2003:                                unlockQNodes[i].params[0].p = pda;
        !          2004:                                unlockQNodes[i].params[1].v =
        !          2005:                                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          2006:                                    0, lu_flag, which_ru);
        !          2007:                        }
        !          2008:                        pda = pda->next;
        !          2009:                }
        !          2010:        }
        !          2011:        /* Step 4. Connect the nodes. */
        !          2012:
        !          2013:        /* Connect header to block node. */
        !          2014:        dag_h->succedents[0] = blockNode;
        !          2015:
        !          2016:        /* Connect block node to read old data nodes. */
        !          2017:        RF_ASSERT(blockNode->numSuccedents ==
        !          2018:            (numDataNodes + (numParityNodes * nfaults)));
        !          2019:        for (i = 0; i < numDataNodes; i++) {
        !          2020:                blockNode->succedents[i] = &readDataNodes[i];
        !          2021:                RF_ASSERT(readDataNodes[i].numAntecedents == 1);
        !          2022:                readDataNodes[i].antecedents[0] = blockNode;
        !          2023:                readDataNodes[i].antType[0] = rf_control;
        !          2024:        }
        !          2025:
        !          2026:        /* Connect block node to read old parity nodes. */
        !          2027:        for (i = 0; i < numParityNodes; i++) {
        !          2028:                blockNode->succedents[numDataNodes + i] = &readParityNodes[i];
        !          2029:                RF_ASSERT(readParityNodes[i].numAntecedents == 1);
        !          2030:                readParityNodes[i].antecedents[0] = blockNode;
        !          2031:                readParityNodes[i].antType[0] = rf_control;
        !          2032:        }
        !          2033:
        !          2034:        /* Connect block node to read old Q nodes. */
        !          2035:        if (nfaults == 2)
        !          2036:                for (i = 0; i < numParityNodes; i++) {
        !          2037:                        blockNode->succedents[numDataNodes +
        !          2038:                            numParityNodes + i] = &readQNodes[i];
        !          2039:                        RF_ASSERT(readQNodes[i].numAntecedents == 1);
        !          2040:                        readQNodes[i].antecedents[0] = blockNode;
        !          2041:                        readQNodes[i].antType[0] = rf_control;
        !          2042:                }
        !          2043:
        !          2044:        /* Connect read old data nodes to write new data nodes. */
        !          2045:        for (i = 0; i < numDataNodes; i++) {
        !          2046:                RF_ASSERT(readDataNodes[i].numSuccedents ==
        !          2047:                    ((nfaults * numParityNodes) + 1));
        !          2048:                RF_ASSERT(writeDataNodes[i].numAntecedents == 1);
        !          2049:                readDataNodes[i].succedents[0] = &writeDataNodes[i];
        !          2050:                writeDataNodes[i].antecedents[0] = &readDataNodes[i];
        !          2051:                writeDataNodes[i].antType[0] = rf_antiData;
        !          2052:        }
        !          2053:
        !          2054:        /* Connect read old data nodes to xor nodes. */
        !          2055:        for (i = 0; i < numDataNodes; i++) {
        !          2056:                for (j = 0; j < numParityNodes; j++) {
        !          2057:                        RF_ASSERT(xorNodes[j].numAntecedents ==
        !          2058:                            numDataNodes + numParityNodes);
        !          2059:                        readDataNodes[i].succedents[1 + j] = &xorNodes[j];
        !          2060:                        xorNodes[j].antecedents[i] = &readDataNodes[i];
        !          2061:                        xorNodes[j].antType[i] = rf_trueData;
        !          2062:                }
        !          2063:        }
        !          2064:
        !          2065:        /* Connect read old data nodes to q nodes. */
        !          2066:        if (nfaults == 2)
        !          2067:                for (i = 0; i < numDataNodes; i++)
        !          2068:                        for (j = 0; j < numParityNodes; j++) {
        !          2069:                                RF_ASSERT(qNodes[j].numAntecedents ==
        !          2070:                                    numDataNodes + numParityNodes);
        !          2071:                                readDataNodes[i].succedents
        !          2072:                                    [1 + numParityNodes + j] = &qNodes[j];
        !          2073:                                qNodes[j].antecedents[i] = &readDataNodes[i];
        !          2074:                                qNodes[j].antType[i] = rf_trueData;
        !          2075:                        }
        !          2076:
        !          2077:        /* Connect read old parity nodes to xor nodes. */
        !          2078:        for (i = 0; i < numParityNodes; i++) {
        !          2079:                for (j = 0; j < numParityNodes; j++) {
        !          2080:                        RF_ASSERT(readParityNodes[i].numSuccedents ==
        !          2081:                            numParityNodes);
        !          2082:                        readParityNodes[i].succedents[j] = &xorNodes[j];
        !          2083:                        xorNodes[j].antecedents[numDataNodes + i] =
        !          2084:                            &readParityNodes[i];
        !          2085:                        xorNodes[j].antType[numDataNodes + i] = rf_trueData;
        !          2086:                }
        !          2087:        }
        !          2088:
        !          2089:        /* Connect read old q nodes to q nodes. */
        !          2090:        if (nfaults == 2)
        !          2091:                for (i = 0; i < numParityNodes; i++) {
        !          2092:                        for (j = 0; j < numParityNodes; j++) {
        !          2093:                                RF_ASSERT(readQNodes[i].numSuccedents ==
        !          2094:                                    numParityNodes);
        !          2095:                                readQNodes[i].succedents[j] = &qNodes[j];
        !          2096:                                qNodes[j].antecedents[numDataNodes + i] =
        !          2097:                                    &readQNodes[i];
        !          2098:                                qNodes[j].antType[numDataNodes + i] =
        !          2099:                                    rf_trueData;
        !          2100:                        }
        !          2101:                }
        !          2102:
        !          2103:        /* Connect xor nodes to the write new parity nodes. */
        !          2104:        for (i = 0; i < numParityNodes; i++) {
        !          2105:                RF_ASSERT(writeParityNodes[i].numAntecedents == numParityNodes);
        !          2106:                for (j = 0; j < numParityNodes; j++) {
        !          2107:                        RF_ASSERT(xorNodes[j].numSuccedents == numParityNodes);
        !          2108:                        xorNodes[i].succedents[j] = &writeParityNodes[j];
        !          2109:                        writeParityNodes[j].antecedents[i] = &xorNodes[i];
        !          2110:                        writeParityNodes[j].antType[i] = rf_trueData;
        !          2111:                }
        !          2112:        }
        !          2113:
        !          2114:        /* Connect q nodes to the write new q nodes. */
        !          2115:        if (nfaults == 2)
        !          2116:                for (i = 0; i < numParityNodes; i++) {
        !          2117:                        RF_ASSERT(writeQNodes[i].numAntecedents ==
        !          2118:                            numParityNodes);
        !          2119:                        for (j = 0; j < numParityNodes; j++) {
        !          2120:                                RF_ASSERT(qNodes[j].numSuccedents == 1);
        !          2121:                                qNodes[i].succedents[j] = &writeQNodes[j];
        !          2122:                                writeQNodes[j].antecedents[i] = &qNodes[i];
        !          2123:                                writeQNodes[j].antType[i] = rf_trueData;
        !          2124:                        }
        !          2125:                }
        !          2126:
        !          2127:        RF_ASSERT(termNode->numAntecedents ==
        !          2128:            (numDataNodes + (nfaults * numParityNodes)));
        !          2129:        RF_ASSERT(termNode->numSuccedents == 0);
        !          2130:        for (i = 0; i < numDataNodes; i++) {
        !          2131:                if (lu_flag) {
        !          2132:                        /* Connect write new data nodes to unlock nodes. */
        !          2133:                        RF_ASSERT(writeDataNodes[i].numSuccedents == 1);
        !          2134:                        RF_ASSERT(unlockDataNodes[i].numAntecedents == 1);
        !          2135:                        writeDataNodes[i].succedents[0] = &unlockDataNodes[i];
        !          2136:                        unlockDataNodes[i].antecedents[0] = &writeDataNodes[i];
        !          2137:                        unlockDataNodes[i].antType[0] = rf_control;
        !          2138:
        !          2139:                        /* Connect unlock nodes to term nodes. */
        !          2140:                        RF_ASSERT(unlockDataNodes[i].numSuccedents == 1);
        !          2141:                        unlockDataNodes[i].succedents[0] = termNode;
        !          2142:                        termNode->antecedents[i] = &unlockDataNodes[i];
        !          2143:                        termNode->antType[i] = rf_control;
        !          2144:                } else {
        !          2145:                        /* Connect write new data nodes to term node. */
        !          2146:                        RF_ASSERT(writeDataNodes[i].numSuccedents == 1);
        !          2147:                        RF_ASSERT(termNode->numAntecedents ==
        !          2148:                            (numDataNodes + (nfaults * numParityNodes)));
        !          2149:                        writeDataNodes[i].succedents[0] = termNode;
        !          2150:                        termNode->antecedents[i] = &writeDataNodes[i];
        !          2151:                        termNode->antType[i] = rf_control;
        !          2152:                }
        !          2153:        }
        !          2154:
        !          2155:        for (i = 0; i < numParityNodes; i++) {
        !          2156:                if (lu_flag) {
        !          2157:                        /* Connect write new parity nodes to unlock nodes. */
        !          2158:                        RF_ASSERT(writeParityNodes[i].numSuccedents == 1);
        !          2159:                        RF_ASSERT(unlockParityNodes[i].numAntecedents == 1);
        !          2160:                        writeParityNodes[i].succedents[0] =
        !          2161:                            &unlockParityNodes[i];
        !          2162:                        unlockParityNodes[i].antecedents[0] =
        !          2163:                            &writeParityNodes[i];
        !          2164:                        unlockParityNodes[i].antType[0] = rf_control;
        !          2165:
        !          2166:                        /* Connect unlock nodes to term node. */
        !          2167:                        RF_ASSERT(unlockParityNodes[i].numSuccedents == 1);
        !          2168:                        unlockParityNodes[i].succedents[0] = termNode;
        !          2169:                        termNode->antecedents[numDataNodes + i] =
        !          2170:                            &unlockParityNodes[i];
        !          2171:                        termNode->antType[numDataNodes + i] = rf_control;
        !          2172:                } else {
        !          2173:                        RF_ASSERT(writeParityNodes[i].numSuccedents == 1);
        !          2174:                        writeParityNodes[i].succedents[0] = termNode;
        !          2175:                        termNode->antecedents[numDataNodes + i] =
        !          2176:                            &writeParityNodes[i];
        !          2177:                        termNode->antType[numDataNodes + i] = rf_control;
        !          2178:                }
        !          2179:        }
        !          2180:
        !          2181:        if (nfaults == 2)
        !          2182:                for (i = 0; i < numParityNodes; i++) {
        !          2183:                        if (lu_flag) {
        !          2184:                                /* Connect write new Q nodes to unlock nodes. */
        !          2185:                                RF_ASSERT(writeQNodes[i].numSuccedents == 1);
        !          2186:                                RF_ASSERT(unlockQNodes[i].numAntecedents == 1);
        !          2187:                                writeQNodes[i].succedents[0] = &unlockQNodes[i];
        !          2188:                                unlockQNodes[i].antecedents[0] =
        !          2189:                                    &writeQNodes[i];
        !          2190:                                unlockQNodes[i].antType[0] = rf_control;
        !          2191:
        !          2192:                                /* Connect unlock nodes to unblock node. */
        !          2193:                                RF_ASSERT(unlockQNodes[i].numSuccedents == 1);
        !          2194:                                unlockQNodes[i].succedents[0] = termNode;
        !          2195:                                termNode->antecedents[numDataNodes +
        !          2196:                                    numParityNodes + i] = &unlockQNodes[i];
        !          2197:                                termNode->antType[numDataNodes +
        !          2198:                                    numParityNodes + i] = rf_control;
        !          2199:                        } else {
        !          2200:                                RF_ASSERT(writeQNodes[i].numSuccedents == 1);
        !          2201:                                writeQNodes[i].succedents[0] = termNode;
        !          2202:                                termNode->antecedents[numDataNodes +
        !          2203:                                    numParityNodes + i] = &writeQNodes[i];
        !          2204:                                termNode->antType[numDataNodes +
        !          2205:                                    numParityNodes + i] = rf_control;
        !          2206:                        }
        !          2207:                }
        !          2208: }
        !          2209:
        !          2210:
        !          2211:
        !          2212: /*****************************************************************************
        !          2213:  * Create a write graph (fault-free or degraded) for RAID level 1.
        !          2214:  *
        !          2215:  * Hdr  Nil -> Wpd -> Nil -> Trm
        !          2216:  *     Nil -> Wsd ->
        !          2217:  *
        !          2218:  * The "Wpd" node writes data to the primary copy in the mirror pair.
        !          2219:  * The "Wsd" node writes data to the secondary copy in the mirror pair.
        !          2220:  *
        !          2221:  * Parameters: raidPtr   - description of the physical array
        !          2222:  *             asmap     - logical & physical addresses for this access
        !          2223:  *             bp        - buffer ptr (holds write data)
        !          2224:  *             flags     - general flags (e.g. disk locking)
        !          2225:  *             allocList - list of memory allocated in DAG creation
        !          2226:  *****************************************************************************/
        !          2227:
        !          2228: void
        !          2229: rf_CreateRaidOneWriteDAGFwd(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *asmap,
        !          2230:     RF_DagHeader_t *dag_h, void *bp, RF_RaidAccessFlags_t flags,
        !          2231:     RF_AllocListElem_t *allocList)
        !          2232: {
        !          2233:        RF_DagNode_t *blockNode, *unblockNode, *termNode;
        !          2234:        RF_DagNode_t *nodes, *wndNode, *wmirNode;
        !          2235:        int nWndNodes, nWmirNodes, i;
        !          2236:        RF_ReconUnitNum_t which_ru;
        !          2237:        RF_PhysDiskAddr_t *pda, *pdaP;
        !          2238:        RF_StripeNum_t parityStripeID;
        !          2239:
        !          2240:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !          2241:            asmap->raidAddress, &which_ru);
        !          2242:        if (rf_dagDebug) {
        !          2243:                printf("[Creating RAID level 1 write DAG]\n");
        !          2244:        }
        !          2245:        /* 2 implies access not SU aligned. */
        !          2246:        nWmirNodes = (asmap->parityInfo->next) ? 2 : 1;
        !          2247:        nWndNodes = (asmap->physInfo->next) ? 2 : 1;
        !          2248:
        !          2249:        /* Alloc the Wnd nodes and the Wmir node. */
        !          2250:        if (asmap->numDataFailed == 1)
        !          2251:                nWndNodes--;
        !          2252:        if (asmap->numParityFailed == 1)
        !          2253:                nWmirNodes--;
        !          2254:
        !          2255:        /*
        !          2256:         * Total number of nodes = nWndNodes + nWmirNodes +
        !          2257:         *                         (block + unblock + terminator)
        !          2258:         */
        !          2259:        RF_CallocAndAdd(nodes, nWndNodes + nWmirNodes + 3,
        !          2260:            sizeof(RF_DagNode_t), (RF_DagNode_t *), allocList);
        !          2261:        i = 0;
        !          2262:        wndNode = &nodes[i];
        !          2263:        i += nWndNodes;
        !          2264:        wmirNode = &nodes[i];
        !          2265:        i += nWmirNodes;
        !          2266:        blockNode = &nodes[i];
        !          2267:        i += 1;
        !          2268:        unblockNode = &nodes[i];
        !          2269:        i += 1;
        !          2270:        termNode = &nodes[i];
        !          2271:        i += 1;
        !          2272:        RF_ASSERT(i == (nWndNodes + nWmirNodes + 3));
        !          2273:
        !          2274:        /* This dag can commit immediately. */
        !          2275:        dag_h->numCommitNodes = 0;
        !          2276:        dag_h->numCommits = 0;
        !          2277:        dag_h->numSuccedents = 1;
        !          2278:
        !          2279:        /* Initialize the unblock and term nodes. */
        !          2280:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          2281:            rf_NullNodeUndoFunc, NULL, (nWndNodes + nWmirNodes),
        !          2282:            0, 0, 0, dag_h, "Nil", allocList);
        !          2283:        rf_InitNode(unblockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          2284:            rf_NullNodeUndoFunc, NULL, 1, (nWndNodes + nWmirNodes),
        !          2285:            0, 0, dag_h, "Nil", allocList);
        !          2286:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !          2287:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", allocList);
        !          2288:
        !          2289:        /* Initialize the wnd nodes. */
        !          2290:        if (nWndNodes > 0) {
        !          2291:                pda = asmap->physInfo;
        !          2292:                for (i = 0; i < nWndNodes; i++) {
        !          2293:                        rf_InitNode(&wndNode[i], rf_wait, RF_FALSE,
        !          2294:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          2295:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !          2296:                            "Wpd", allocList);
        !          2297:                        RF_ASSERT(pda != NULL);
        !          2298:                        wndNode[i].params[0].p = pda;
        !          2299:                        wndNode[i].params[1].p = pda->bufPtr;
        !          2300:                        wndNode[i].params[2].v = parityStripeID;
        !          2301:                        wndNode[i].params[3].v =
        !          2302:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          2303:                            0, 0, which_ru);
        !          2304:                        pda = pda->next;
        !          2305:                }
        !          2306:                RF_ASSERT(pda == NULL);
        !          2307:        }
        !          2308:        /* Initialize the mirror nodes. */
        !          2309:        if (nWmirNodes > 0) {
        !          2310:                pda = asmap->physInfo;
        !          2311:                pdaP = asmap->parityInfo;
        !          2312:                for (i = 0; i < nWmirNodes; i++) {
        !          2313:                        rf_InitNode(&wmirNode[i], rf_wait, RF_FALSE,
        !          2314:                            rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !          2315:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !          2316:                            "Wsd", allocList);
        !          2317:                        RF_ASSERT(pda != NULL);
        !          2318:                        wmirNode[i].params[0].p = pdaP;
        !          2319:                        wmirNode[i].params[1].p = pda->bufPtr;
        !          2320:                        wmirNode[i].params[2].v = parityStripeID;
        !          2321:                        wmirNode[i].params[3].v =
        !          2322:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !          2323:                            0, 0, which_ru);
        !          2324:                        pda = pda->next;
        !          2325:                        pdaP = pdaP->next;
        !          2326:                }
        !          2327:                RF_ASSERT(pda == NULL);
        !          2328:                RF_ASSERT(pdaP == NULL);
        !          2329:        }
        !          2330:        /* Link the header node to the block node. */
        !          2331:        RF_ASSERT(dag_h->numSuccedents == 1);
        !          2332:        RF_ASSERT(blockNode->numAntecedents == 0);
        !          2333:        dag_h->succedents[0] = blockNode;
        !          2334:
        !          2335:        /* Link the block node to the write nodes. */
        !          2336:        RF_ASSERT(blockNode->numSuccedents == (nWndNodes + nWmirNodes));
        !          2337:        for (i = 0; i < nWndNodes; i++) {
        !          2338:                RF_ASSERT(wndNode[i].numAntecedents == 1);
        !          2339:                blockNode->succedents[i] = &wndNode[i];
        !          2340:                wndNode[i].antecedents[0] = blockNode;
        !          2341:                wndNode[i].antType[0] = rf_control;
        !          2342:        }
        !          2343:        for (i = 0; i < nWmirNodes; i++) {
        !          2344:                RF_ASSERT(wmirNode[i].numAntecedents == 1);
        !          2345:                blockNode->succedents[i + nWndNodes] = &wmirNode[i];
        !          2346:                wmirNode[i].antecedents[0] = blockNode;
        !          2347:                wmirNode[i].antType[0] = rf_control;
        !          2348:        }
        !          2349:
        !          2350:        /* Link the write nodes to the unblock node. */
        !          2351:        RF_ASSERT(unblockNode->numAntecedents == (nWndNodes + nWmirNodes));
        !          2352:        for (i = 0; i < nWndNodes; i++) {
        !          2353:                RF_ASSERT(wndNode[i].numSuccedents == 1);
        !          2354:                wndNode[i].succedents[0] = unblockNode;
        !          2355:                unblockNode->antecedents[i] = &wndNode[i];
        !          2356:                unblockNode->antType[i] = rf_control;
        !          2357:        }
        !          2358:        for (i = 0; i < nWmirNodes; i++) {
        !          2359:                RF_ASSERT(wmirNode[i].numSuccedents == 1);
        !          2360:                wmirNode[i].succedents[0] = unblockNode;
        !          2361:                unblockNode->antecedents[i + nWndNodes] = &wmirNode[i];
        !          2362:                unblockNode->antType[i + nWndNodes] = rf_control;
        !          2363:        }
        !          2364:
        !          2365:        /* Link the unblock node to the term node. */
        !          2366:        RF_ASSERT(unblockNode->numSuccedents == 1);
        !          2367:        RF_ASSERT(termNode->numAntecedents == 1);
        !          2368:        RF_ASSERT(termNode->numSuccedents == 0);
        !          2369:        unblockNode->succedents[0] = termNode;
        !          2370:        termNode->antecedents[0] = unblockNode;
        !          2371:        termNode->antType[0] = rf_control;
        !          2372:
        !          2373:        return;
        !          2374: }

CVSweb