[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

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