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

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

1.1     ! nbrk        1: /*     $OpenBSD: rf_dagdegrd.c,v 1.6 2006/07/09 22:10:05 mk Exp $      */
        !             2: /*     $NetBSD: rf_dagdegrd.c,v 1.5 2000/01/07 03:40:57 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_dagdegrd.c
        !            33:  *
        !            34:  * Code for creating degraded read DAGs.
        !            35:  */
        !            36:
        !            37: #include "rf_types.h"
        !            38: #include "rf_raid.h"
        !            39: #include "rf_dag.h"
        !            40: #include "rf_dagutils.h"
        !            41: #include "rf_dagfuncs.h"
        !            42: #include "rf_debugMem.h"
        !            43: #include "rf_memchunk.h"
        !            44: #include "rf_general.h"
        !            45: #include "rf_dagdegrd.h"
        !            46:
        !            47:
        !            48: /*****************************************************************************
        !            49:  *
        !            50:  * General comments on DAG creation:
        !            51:  *
        !            52:  * All DAGs in this file use roll-away error recovery. Each DAG has a single
        !            53:  * commit node, usually called "Cmt". If an error occurs before the Cmt node
        !            54:  * is reached, the execution engine will halt forward execution and work
        !            55:  * backward through the graph, executing the undo functions. Assuming that
        !            56:  * each node in the graph prior to the Cmt node are undoable and atomic - or -
        !            57:  * does not make changes to permanent state, the graph will fail atomically.
        !            58:  * If an error occurs after the Cmt node executes, the engine will roll-forward
        !            59:  * through the graph, blindly executing nodes until it reaches the end.
        !            60:  * If a graph reaches the end, it is assumed to have completed successfully.
        !            61:  *
        !            62:  * A graph has only 1 Cmt node.
        !            63:  *
        !            64:  *****************************************************************************/
        !            65:
        !            66:
        !            67: /*****************************************************************************
        !            68:  *
        !            69:  * The following wrappers map the standard DAG creation interface to the
        !            70:  * DAG creation routines. Additionally, these wrappers enable experimentation
        !            71:  * with new DAG structures by providing an extra level of indirection, allowing
        !            72:  * the DAG creation routines to be replaced at this single point.
        !            73:  *
        !            74:  *****************************************************************************/
        !            75:
        !            76: void
        !            77: rf_CreateRaidFiveDegradedReadDAG(
        !            78:     RF_Raid_t                  *raidPtr,
        !            79:     RF_AccessStripeMap_t       *asmap,
        !            80:     RF_DagHeader_t             *dag_h,
        !            81:     void                       *bp,
        !            82:     RF_RaidAccessFlags_t        flags,
        !            83:     RF_AllocListElem_t         *allocList)
        !            84: {
        !            85:        rf_CreateDegradedReadDAG(raidPtr, asmap, dag_h, bp, flags, allocList,
        !            86:            &rf_xorRecoveryFuncs);
        !            87: }
        !            88:
        !            89:
        !            90: /*****************************************************************************
        !            91:  *
        !            92:  * DAG creation code begins here.
        !            93:  *
        !            94:  *****************************************************************************/
        !            95:
        !            96:
        !            97: /*****************************************************************************
        !            98:  * Create a degraded read DAG for RAID level 1.
        !            99:  *
        !           100:  * Hdr -> Nil -> R(p/s)d -> Commit -> Trm
        !           101:  *
        !           102:  * The "Rd" node reads data from the surviving disk in the mirror pair.
        !           103:  *   Rpd - read of primary copy
        !           104:  *   Rsd - read of secondary copy
        !           105:  *
        !           106:  * Parameters: raidPtr   - description of the physical array
        !           107:  *             asmap     - logical & physical addresses for this access
        !           108:  *             bp        - buffer ptr (for holding write data)
        !           109:  *             flags     - general flags (e.g. disk locking)
        !           110:  *             allocList - list of memory allocated in DAG creation
        !           111:  *****************************************************************************/
        !           112:
        !           113: void
        !           114: rf_CreateRaidOneDegradedReadDAG(
        !           115:     RF_Raid_t                  *raidPtr,
        !           116:     RF_AccessStripeMap_t       *asmap,
        !           117:     RF_DagHeader_t             *dag_h,
        !           118:     void                       *bp,
        !           119:     RF_RaidAccessFlags_t        flags,
        !           120:     RF_AllocListElem_t         *allocList)
        !           121: {
        !           122:        RF_DagNode_t *nodes, *rdNode, *blockNode, *commitNode, *termNode;
        !           123:        RF_StripeNum_t parityStripeID;
        !           124:        RF_ReconUnitNum_t which_ru;
        !           125:        RF_PhysDiskAddr_t *pda;
        !           126:        int useMirror, i;
        !           127:
        !           128:        useMirror = 0;
        !           129:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !           130:            asmap->raidAddress, &which_ru);
        !           131:        if (rf_dagDebug) {
        !           132:                printf("[Creating RAID level 1 degraded read DAG]\n");
        !           133:        }
        !           134:        dag_h->creator = "RaidOneDegradedReadDAG";
        !           135:        /* Alloc the Wnd nodes and the Wmir node. */
        !           136:        if (asmap->numDataFailed == 0)
        !           137:                useMirror = RF_FALSE;
        !           138:        else
        !           139:                useMirror = RF_TRUE;
        !           140:
        !           141:        /* Total number of nodes = 1 + (block + commit + terminator). */
        !           142:        RF_CallocAndAdd(nodes, 4, sizeof(RF_DagNode_t), (RF_DagNode_t *),
        !           143:            allocList);
        !           144:        i = 0;
        !           145:        rdNode = &nodes[i];
        !           146:        i++;
        !           147:        blockNode = &nodes[i];
        !           148:        i++;
        !           149:        commitNode = &nodes[i];
        !           150:        i++;
        !           151:        termNode = &nodes[i];
        !           152:        i++;
        !           153:
        !           154:        /*
        !           155:         * This dag can not commit until the commit node is reached. Errors
        !           156:         * prior to the commit point imply the dag has failed and must be
        !           157:         * retried.
        !           158:         */
        !           159:        dag_h->numCommitNodes = 1;
        !           160:        dag_h->numCommits = 0;
        !           161:        dag_h->numSuccedents = 1;
        !           162:
        !           163:        /* Initialize the block, commit, and terminator nodes. */
        !           164:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           165:            rf_NullNodeUndoFunc, NULL, 1, 0, 0, 0, dag_h, "Nil", allocList);
        !           166:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           167:            rf_NullNodeUndoFunc, NULL, 1, 1, 0, 0, dag_h, "Cmt", allocList);
        !           168:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           169:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", allocList);
        !           170:
        !           171:        pda = asmap->physInfo;
        !           172:        RF_ASSERT(pda != NULL);
        !           173:        /* parityInfo must describe entire parity unit. */
        !           174:        RF_ASSERT(asmap->parityInfo->next == NULL);
        !           175:
        !           176:        /* Initialize the data node. */
        !           177:        if (!useMirror) {
        !           178:                /* Read primary copy of data. */
        !           179:                rf_InitNode(rdNode, rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           180:                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           181:                    dag_h, "Rpd", allocList);
        !           182:                rdNode->params[0].p = pda;
        !           183:                rdNode->params[1].p = pda->bufPtr;
        !           184:                rdNode->params[2].v = parityStripeID;
        !           185:                rdNode->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           186:                    0, 0, which_ru);
        !           187:        } else {
        !           188:                /* Read secondary copy of data. */
        !           189:                rf_InitNode(rdNode, rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           190:                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           191:                    dag_h, "Rsd", allocList);
        !           192:                rdNode->params[0].p = asmap->parityInfo;
        !           193:                rdNode->params[1].p = pda->bufPtr;
        !           194:                rdNode->params[2].v = parityStripeID;
        !           195:                rdNode->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           196:                    0, 0, which_ru);
        !           197:        }
        !           198:
        !           199:        /* Connect header to block node. */
        !           200:        RF_ASSERT(dag_h->numSuccedents == 1);
        !           201:        RF_ASSERT(blockNode->numAntecedents == 0);
        !           202:        dag_h->succedents[0] = blockNode;
        !           203:
        !           204:        /* Connect block node to rdnode. */
        !           205:        RF_ASSERT(blockNode->numSuccedents == 1);
        !           206:        RF_ASSERT(rdNode->numAntecedents == 1);
        !           207:        blockNode->succedents[0] = rdNode;
        !           208:        rdNode->antecedents[0] = blockNode;
        !           209:        rdNode->antType[0] = rf_control;
        !           210:
        !           211:        /* Connect rdnode to commit node. */
        !           212:        RF_ASSERT(rdNode->numSuccedents == 1);
        !           213:        RF_ASSERT(commitNode->numAntecedents == 1);
        !           214:        rdNode->succedents[0] = commitNode;
        !           215:        commitNode->antecedents[0] = rdNode;
        !           216:        commitNode->antType[0] = rf_control;
        !           217:
        !           218:        /* Connect commit node to terminator. */
        !           219:        RF_ASSERT(commitNode->numSuccedents == 1);
        !           220:        RF_ASSERT(termNode->numAntecedents == 1);
        !           221:        RF_ASSERT(termNode->numSuccedents == 0);
        !           222:        commitNode->succedents[0] = termNode;
        !           223:        termNode->antecedents[0] = commitNode;
        !           224:        termNode->antType[0] = rf_control;
        !           225: }
        !           226:
        !           227:
        !           228: /*****************************************************************************
        !           229:  *
        !           230:  * Create a DAG to perform a degraded-mode read of data within one stripe.
        !           231:  * This DAG is as follows:
        !           232:  *
        !           233:  * Hdr -> Block -> Rud -> Xor -> Cmt -> T
        !           234:  *             -> Rrd ->
        !           235:  *             -> Rp -->
        !           236:  *
        !           237:  * Each R node is a successor of the L node.
        !           238:  * One successor arc from each R node goes to C, and the other to X.
        !           239:  * There is one Rud for each chunk of surviving user data requested by the
        !           240:  * user, and one Rrd for each chunk of surviving user data _not_ being read by
        !           241:  * the user.
        !           242:  * R = read, ud = user data, rd = recovery (surviving) data, p = parity
        !           243:  * X = XOR, C = Commit, T = terminate
        !           244:  *
        !           245:  * The block node guarantees a single source node.
        !           246:  *
        !           247:  * Note:  The target buffer for the XOR node is set to the actual user buffer
        !           248:  * where the failed data is supposed to end up. This buffer is zero'd by the
        !           249:  * code here. Thus, if you create a degraded read dag, use it, and then
        !           250:  * re-use, you have to be sure to zero the target buffer prior to the re-use.
        !           251:  *
        !           252:  * The recfunc argument at the end specifies the name and function used for
        !           253:  * the redundancy recovery function.
        !           254:  *
        !           255:  *****************************************************************************/
        !           256:
        !           257: void
        !           258: rf_CreateDegradedReadDAG(
        !           259:     RF_Raid_t                  *raidPtr,
        !           260:     RF_AccessStripeMap_t       *asmap,
        !           261:     RF_DagHeader_t             *dag_h,
        !           262:     void                       *bp,
        !           263:     RF_RaidAccessFlags_t        flags,
        !           264:     RF_AllocListElem_t         *allocList,
        !           265:     RF_RedFuncs_t              *recFunc)
        !           266: {
        !           267:        RF_DagNode_t *nodes, *rudNodes, *rrdNodes, *xorNode, *blockNode;
        !           268:        RF_DagNode_t *commitNode, *rpNode, *termNode;
        !           269:        int nNodes, nRrdNodes, nRudNodes, nXorBufs, i;
        !           270:        int j, paramNum;
        !           271:        RF_SectorCount_t sectorsPerSU;
        !           272:        RF_ReconUnitNum_t which_ru;
        !           273:        char *overlappingPDAs;          /* A temporary array of flags. */
        !           274:        RF_AccessStripeMapHeader_t *new_asm_h[2];
        !           275:        RF_PhysDiskAddr_t *pda, *parityPDA;
        !           276:        RF_StripeNum_t parityStripeID;
        !           277:        RF_PhysDiskAddr_t *failedPDA;
        !           278:        RF_RaidLayout_t *layoutPtr;
        !           279:        char *rpBuf;
        !           280:
        !           281:        layoutPtr = &(raidPtr->Layout);
        !           282:        /*
        !           283:         * failedPDA points to the pda within the asm that targets
        !           284:         * the failed disk.
        !           285:         */
        !           286:        failedPDA = asmap->failedPDAs[0];
        !           287:        parityStripeID = rf_RaidAddressToParityStripeID(layoutPtr,
        !           288:            asmap->raidAddress, &which_ru);
        !           289:        sectorsPerSU = layoutPtr->sectorsPerStripeUnit;
        !           290:
        !           291:        if (rf_dagDebug) {
        !           292:                printf("[Creating degraded read DAG]\n");
        !           293:        }
        !           294:        RF_ASSERT(asmap->numDataFailed == 1);
        !           295:        dag_h->creator = "DegradedReadDAG";
        !           296:
        !           297:        /*
        !           298:         * Generate two ASMs identifying the surviving data we need
        !           299:         * in order to recover the lost data.
        !           300:         */
        !           301:
        !           302:        /* overlappingPDAs array must be zero'd. */
        !           303:        RF_Calloc(overlappingPDAs, asmap->numStripeUnitsAccessed,
        !           304:            sizeof(char), (char *));
        !           305:        rf_GenerateFailedAccessASMs(raidPtr, asmap, failedPDA, dag_h,
        !           306:            new_asm_h, &nXorBufs, &rpBuf, overlappingPDAs, allocList);
        !           307:
        !           308:        /*
        !           309:         * Create all the nodes at once.
        !           310:         *
        !           311:         * -1 because no access is generated for the failed pda.
        !           312:         */
        !           313:        nRudNodes = asmap->numStripeUnitsAccessed - 1;
        !           314:        nRrdNodes = ((new_asm_h[0]) ?
        !           315:            new_asm_h[0]->stripeMap->numStripeUnitsAccessed : 0) +
        !           316:            ((new_asm_h[1]) ?
        !           317:            new_asm_h[1]->stripeMap->numStripeUnitsAccessed : 0);
        !           318:        nNodes = 5 + nRudNodes + nRrdNodes;     /*
        !           319:                                                 * lock, unlock, xor, Rp,
        !           320:                                                 * Rud, Rrd
        !           321:                                                 */
        !           322:        RF_CallocAndAdd(nodes, nNodes, sizeof(RF_DagNode_t), (RF_DagNode_t *),
        !           323:            allocList);
        !           324:        i = 0;
        !           325:        blockNode = &nodes[i];
        !           326:        i++;
        !           327:        commitNode = &nodes[i];
        !           328:        i++;
        !           329:        xorNode = &nodes[i];
        !           330:        i++;
        !           331:        rpNode = &nodes[i];
        !           332:        i++;
        !           333:        termNode = &nodes[i];
        !           334:        i++;
        !           335:        rudNodes = &nodes[i];
        !           336:        i += nRudNodes;
        !           337:        rrdNodes = &nodes[i];
        !           338:        i += nRrdNodes;
        !           339:        RF_ASSERT(i == nNodes);
        !           340:
        !           341:        /* Initialize nodes. */
        !           342:        dag_h->numCommitNodes = 1;
        !           343:        dag_h->numCommits = 0;
        !           344:        /*
        !           345:         * This dag can not commit until the commit node is reached.
        !           346:         * Errors prior to the commit point imply the dag has failed.
        !           347:         */
        !           348:        dag_h->numSuccedents = 1;
        !           349:
        !           350:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           351:            rf_NullNodeUndoFunc, NULL, nRudNodes + nRrdNodes + 1, 0, 0, 0,
        !           352:            dag_h, "Nil", allocList);
        !           353:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           354:            rf_NullNodeUndoFunc, NULL, 1, 1, 0, 0, dag_h, "Cmt", allocList);
        !           355:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           356:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", allocList);
        !           357:        rf_InitNode(xorNode, rf_wait, RF_FALSE, recFunc->simple,
        !           358:            rf_NullNodeUndoFunc, NULL, 1, nRudNodes + nRrdNodes + 1,
        !           359:            2 * nXorBufs + 2, 1, dag_h, recFunc->SimpleName, allocList);
        !           360:
        !           361:        /* Fill in the Rud nodes. */
        !           362:        for (pda = asmap->physInfo, i = 0; i < nRudNodes;
        !           363:             i++, pda = pda->next) {
        !           364:                if (pda == failedPDA) {
        !           365:                        i--;
        !           366:                        continue;
        !           367:                }
        !           368:                rf_InitNode(&rudNodes[i], rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           369:                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           370:                    dag_h, "Rud", allocList);
        !           371:                RF_ASSERT(pda);
        !           372:                rudNodes[i].params[0].p = pda;
        !           373:                rudNodes[i].params[1].p = pda->bufPtr;
        !           374:                rudNodes[i].params[2].v = parityStripeID;
        !           375:                rudNodes[i].params[3].v =
        !           376:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           377:        }
        !           378:
        !           379:        /* Fill in the Rrd nodes. */
        !           380:        i = 0;
        !           381:        if (new_asm_h[0]) {
        !           382:                for (pda = new_asm_h[0]->stripeMap->physInfo;
        !           383:                     i < new_asm_h[0]->stripeMap->numStripeUnitsAccessed;
        !           384:                     i++, pda = pda->next) {
        !           385:                        rf_InitNode(&rrdNodes[i], rf_wait, RF_FALSE,
        !           386:                            rf_DiskReadFunc, rf_DiskReadUndoFunc,
        !           387:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           388:                            "Rrd", allocList);
        !           389:                        RF_ASSERT(pda);
        !           390:                        rrdNodes[i].params[0].p = pda;
        !           391:                        rrdNodes[i].params[1].p = pda->bufPtr;
        !           392:                        rrdNodes[i].params[2].v = parityStripeID;
        !           393:                        rrdNodes[i].params[3].v =
        !           394:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0,
        !           395:                            which_ru);
        !           396:                }
        !           397:        }
        !           398:        if (new_asm_h[1]) {
        !           399:                for (j = 0, pda = new_asm_h[1]->stripeMap->physInfo;
        !           400:                    j < new_asm_h[1]->stripeMap->numStripeUnitsAccessed;
        !           401:                    j++, pda = pda->next) {
        !           402:                        rf_InitNode(&rrdNodes[i + j], rf_wait, RF_FALSE,
        !           403:                            rf_DiskReadFunc, rf_DiskReadUndoFunc,
        !           404:                            rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           405:                            "Rrd", allocList);
        !           406:                        RF_ASSERT(pda);
        !           407:                        rrdNodes[i + j].params[0].p = pda;
        !           408:                        rrdNodes[i + j].params[1].p = pda->bufPtr;
        !           409:                        rrdNodes[i + j].params[2].v = parityStripeID;
        !           410:                        rrdNodes[i + j].params[3].v =
        !           411:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0,
        !           412:                            which_ru);
        !           413:                }
        !           414:        }
        !           415:        /* Make a PDA for the parity unit. */
        !           416:        RF_MallocAndAdd(parityPDA, sizeof(RF_PhysDiskAddr_t),
        !           417:            (RF_PhysDiskAddr_t *), allocList);
        !           418:        parityPDA->row = asmap->parityInfo->row;
        !           419:        parityPDA->col = asmap->parityInfo->col;
        !           420:        parityPDA->startSector = ((asmap->parityInfo->startSector /
        !           421:            sectorsPerSU) * sectorsPerSU) +
        !           422:            (failedPDA->startSector % sectorsPerSU);
        !           423:        parityPDA->numSector = failedPDA->numSector;
        !           424:
        !           425:        /* Initialize the Rp node. */
        !           426:        rf_InitNode(rpNode, rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           427:            rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h,
        !           428:            "Rp ", allocList);
        !           429:        rpNode->params[0].p = parityPDA;
        !           430:        rpNode->params[1].p = rpBuf;
        !           431:        rpNode->params[2].v = parityStripeID;
        !           432:        rpNode->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0,
        !           433:            which_ru);
        !           434:
        !           435:        /*
        !           436:         * The last and nastiest step is to assign all
        !           437:         * the parameters of the Xor node.
        !           438:         */
        !           439:        paramNum = 0;
        !           440:        for (i = 0; i < nRrdNodes; i++) {
        !           441:                /* All the Rrd nodes need to be xored together. */
        !           442:                xorNode->params[paramNum++] = rrdNodes[i].params[0];
        !           443:                xorNode->params[paramNum++] = rrdNodes[i].params[1];
        !           444:        }
        !           445:        for (i = 0; i < nRudNodes; i++) {
        !           446:                /* Any Rud nodes that overlap the failed access need to be
        !           447:                 * xored in. */
        !           448:                if (overlappingPDAs[i]) {
        !           449:                        RF_MallocAndAdd(pda, sizeof(RF_PhysDiskAddr_t),
        !           450:                            (RF_PhysDiskAddr_t *), allocList);
        !           451:                        bcopy((char *) rudNodes[i].params[0].p, (char *) pda,
        !           452:                            sizeof(RF_PhysDiskAddr_t));
        !           453:                        rf_RangeRestrictPDA(raidPtr, failedPDA, pda,
        !           454:                            RF_RESTRICT_DOBUFFER, 0);
        !           455:                        xorNode->params[paramNum++].p = pda;
        !           456:                        xorNode->params[paramNum++].p = pda->bufPtr;
        !           457:                }
        !           458:        }
        !           459:        RF_Free(overlappingPDAs, asmap->numStripeUnitsAccessed * sizeof(char));
        !           460:
        !           461:        /* Install parity pda as last set of params to be xor'd. */
        !           462:        xorNode->params[paramNum++].p = parityPDA;
        !           463:        xorNode->params[paramNum++].p = rpBuf;
        !           464:
        !           465:        /*
        !           466:         * The last 2 params to the recovery xor node are
        !           467:         * the failed PDA and the raidPtr.
        !           468:         */
        !           469:        xorNode->params[paramNum++].p = failedPDA;
        !           470:        xorNode->params[paramNum++].p = raidPtr;
        !           471:        RF_ASSERT(paramNum == 2 * nXorBufs + 2);
        !           472:
        !           473:        /*
        !           474:         * The xor node uses results[0] as the target buffer.
        !           475:         * Set pointer and zero the buffer. In the kernel, this
        !           476:         * may be a user buffer in which case we have to remap it.
        !           477:         */
        !           478:        xorNode->results[0] = failedPDA->bufPtr;
        !           479:        RF_BZERO(bp, failedPDA->bufPtr, rf_RaidAddressToByte(raidPtr,
        !           480:            failedPDA->numSector));
        !           481:
        !           482:        /* Connect nodes to form graph. */
        !           483:        /* Connect the header to the block node. */
        !           484:        RF_ASSERT(dag_h->numSuccedents == 1);
        !           485:        RF_ASSERT(blockNode->numAntecedents == 0);
        !           486:        dag_h->succedents[0] = blockNode;
        !           487:
        !           488:        /* Connect the block node to the read nodes. */
        !           489:        RF_ASSERT(blockNode->numSuccedents == (1 + nRrdNodes + nRudNodes));
        !           490:        RF_ASSERT(rpNode->numAntecedents == 1);
        !           491:        blockNode->succedents[0] = rpNode;
        !           492:        rpNode->antecedents[0] = blockNode;
        !           493:        rpNode->antType[0] = rf_control;
        !           494:        for (i = 0; i < nRrdNodes; i++) {
        !           495:                RF_ASSERT(rrdNodes[i].numSuccedents == 1);
        !           496:                blockNode->succedents[1 + i] = &rrdNodes[i];
        !           497:                rrdNodes[i].antecedents[0] = blockNode;
        !           498:                rrdNodes[i].antType[0] = rf_control;
        !           499:        }
        !           500:        for (i = 0; i < nRudNodes; i++) {
        !           501:                RF_ASSERT(rudNodes[i].numSuccedents == 1);
        !           502:                blockNode->succedents[1 + nRrdNodes + i] = &rudNodes[i];
        !           503:                rudNodes[i].antecedents[0] = blockNode;
        !           504:                rudNodes[i].antType[0] = rf_control;
        !           505:        }
        !           506:
        !           507:        /* Connect the read nodes to the xor node. */
        !           508:        RF_ASSERT(xorNode->numAntecedents == (1 + nRrdNodes + nRudNodes));
        !           509:        RF_ASSERT(rpNode->numSuccedents == 1);
        !           510:        rpNode->succedents[0] = xorNode;
        !           511:        xorNode->antecedents[0] = rpNode;
        !           512:        xorNode->antType[0] = rf_trueData;
        !           513:        for (i = 0; i < nRrdNodes; i++) {
        !           514:                RF_ASSERT(rrdNodes[i].numSuccedents == 1);
        !           515:                rrdNodes[i].succedents[0] = xorNode;
        !           516:                xorNode->antecedents[1 + i] = &rrdNodes[i];
        !           517:                xorNode->antType[1 + i] = rf_trueData;
        !           518:        }
        !           519:        for (i = 0; i < nRudNodes; i++) {
        !           520:                RF_ASSERT(rudNodes[i].numSuccedents == 1);
        !           521:                rudNodes[i].succedents[0] = xorNode;
        !           522:                xorNode->antecedents[1 + nRrdNodes + i] = &rudNodes[i];
        !           523:                xorNode->antType[1 + nRrdNodes + i] = rf_trueData;
        !           524:        }
        !           525:
        !           526:        /* Connect the xor node to the commit node. */
        !           527:        RF_ASSERT(xorNode->numSuccedents == 1);
        !           528:        RF_ASSERT(commitNode->numAntecedents == 1);
        !           529:        xorNode->succedents[0] = commitNode;
        !           530:        commitNode->antecedents[0] = xorNode;
        !           531:        commitNode->antType[0] = rf_control;
        !           532:
        !           533:        /* Connect the termNode to the commit node. */
        !           534:        RF_ASSERT(commitNode->numSuccedents == 1);
        !           535:        RF_ASSERT(termNode->numAntecedents == 1);
        !           536:        RF_ASSERT(termNode->numSuccedents == 0);
        !           537:        commitNode->succedents[0] = termNode;
        !           538:        termNode->antType[0] = rf_control;
        !           539:        termNode->antecedents[0] = commitNode;
        !           540: }
        !           541:
        !           542:
        !           543: /*****************************************************************************
        !           544:  * Create a degraded read DAG for Chained Declustering.
        !           545:  *
        !           546:  * Hdr -> Nil -> R(p/s)d -> Cmt -> Trm
        !           547:  *
        !           548:  * The "Rd" node reads data from the surviving disk in the mirror pair
        !           549:  *   Rpd - read of primary copy
        !           550:  *   Rsd - read of secondary copy
        !           551:  *
        !           552:  * Parameters:  raidPtr          - description of the physical array
        !           553:  *             asmap     - logical & physical addresses for this access
        !           554:  *             bp        - buffer ptr (for holding write data)
        !           555:  *             flags     - general flags (e.g. disk locking)
        !           556:  *             allocList - list of memory allocated in DAG creation
        !           557:  *****************************************************************************/
        !           558:
        !           559: void
        !           560: rf_CreateRaidCDegradedReadDAG(
        !           561:     RF_Raid_t                  *raidPtr,
        !           562:     RF_AccessStripeMap_t       *asmap,
        !           563:     RF_DagHeader_t             *dag_h,
        !           564:     void                       *bp,
        !           565:     RF_RaidAccessFlags_t        flags,
        !           566:     RF_AllocListElem_t         *allocList
        !           567: )
        !           568: {
        !           569:        RF_DagNode_t *nodes, *rdNode, *blockNode, *commitNode, *termNode;
        !           570:        RF_StripeNum_t parityStripeID;
        !           571:        int useMirror, i, shiftable;
        !           572:        RF_ReconUnitNum_t which_ru;
        !           573:        RF_PhysDiskAddr_t *pda;
        !           574:
        !           575:        if ((asmap->numDataFailed + asmap->numParityFailed) == 0) {
        !           576:                shiftable = RF_TRUE;
        !           577:        } else {
        !           578:                shiftable = RF_FALSE;
        !           579:        }
        !           580:        useMirror = 0;
        !           581:        parityStripeID = rf_RaidAddressToParityStripeID(&(raidPtr->Layout),
        !           582:            asmap->raidAddress, &which_ru);
        !           583:
        !           584:        if (rf_dagDebug) {
        !           585:                printf("[Creating RAID C degraded read DAG]\n");
        !           586:        }
        !           587:        dag_h->creator = "RaidCDegradedReadDAG";
        !           588:        /* Alloc the Wnd nodes and the Wmir node. */
        !           589:        if (asmap->numDataFailed == 0)
        !           590:                useMirror = RF_FALSE;
        !           591:        else
        !           592:                useMirror = RF_TRUE;
        !           593:
        !           594:        /* total number of nodes = 1 + (block + commit + terminator) */
        !           595:        RF_CallocAndAdd(nodes, 4, sizeof(RF_DagNode_t), (RF_DagNode_t *),
        !           596:            allocList);
        !           597:        i = 0;
        !           598:        rdNode = &nodes[i];
        !           599:        i++;
        !           600:        blockNode = &nodes[i];
        !           601:        i++;
        !           602:        commitNode = &nodes[i];
        !           603:        i++;
        !           604:        termNode = &nodes[i];
        !           605:        i++;
        !           606:
        !           607:        /*
        !           608:         * This dag can not commit until the commit node is reached.
        !           609:         * Errors prior to the commit point imply the dag has failed
        !           610:         * and must be retried.
        !           611:         */
        !           612:        dag_h->numCommitNodes = 1;
        !           613:        dag_h->numCommits = 0;
        !           614:        dag_h->numSuccedents = 1;
        !           615:
        !           616:        /* initialize the block, commit, and terminator nodes */
        !           617:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           618:            rf_NullNodeUndoFunc, NULL, 1, 0, 0, 0, dag_h, "Nil", allocList);
        !           619:        rf_InitNode(commitNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           620:            rf_NullNodeUndoFunc, NULL, 1, 1, 0, 0, dag_h, "Cmt", allocList);
        !           621:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           622:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", allocList);
        !           623:
        !           624:        pda = asmap->physInfo;
        !           625:        RF_ASSERT(pda != NULL);
        !           626:        /* ParityInfo must describe entire parity unit. */
        !           627:        RF_ASSERT(asmap->parityInfo->next == NULL);
        !           628:
        !           629:        /* Initialize the data node. */
        !           630:        if (!useMirror) {
        !           631:                rf_InitNode(rdNode, rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           632:                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           633:                    dag_h, "Rpd", allocList);
        !           634:                if (shiftable && rf_compute_workload_shift(raidPtr, pda)) {
        !           635:                        /* Shift this read to the next disk in line. */
        !           636:                        rdNode->params[0].p = asmap->parityInfo;
        !           637:                        rdNode->params[1].p = pda->bufPtr;
        !           638:                        rdNode->params[2].v = parityStripeID;
        !           639:                        rdNode->params[3].v = RF_CREATE_PARAM3(
        !           640:                            RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           641:                } else {
        !           642:                        /* Read primary copy. */
        !           643:                        rdNode->params[0].p = pda;
        !           644:                        rdNode->params[1].p = pda->bufPtr;
        !           645:                        rdNode->params[2].v = parityStripeID;
        !           646:                        rdNode->params[3].v = RF_CREATE_PARAM3(
        !           647:                            RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           648:                }
        !           649:        } else {
        !           650:                /* Read secondary copy of data. */
        !           651:                rf_InitNode(rdNode, rf_wait, RF_FALSE, rf_DiskReadFunc,
        !           652:                    rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 1, 1, 4, 0,
        !           653:                    dag_h, "Rsd", allocList);
        !           654:                rdNode->params[0].p = asmap->parityInfo;
        !           655:                rdNode->params[1].p = pda->bufPtr;
        !           656:                rdNode->params[2].v = parityStripeID;
        !           657:                rdNode->params[3].v =
        !           658:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           659:        }
        !           660:
        !           661:        /* Connect header to block node. */
        !           662:        RF_ASSERT(dag_h->numSuccedents == 1);
        !           663:        RF_ASSERT(blockNode->numAntecedents == 0);
        !           664:        dag_h->succedents[0] = blockNode;
        !           665:
        !           666:        /* Connect block node to rdnode. */
        !           667:        RF_ASSERT(blockNode->numSuccedents == 1);
        !           668:        RF_ASSERT(rdNode->numAntecedents == 1);
        !           669:        blockNode->succedents[0] = rdNode;
        !           670:        rdNode->antecedents[0] = blockNode;
        !           671:        rdNode->antType[0] = rf_control;
        !           672:
        !           673:        /* Connect rdnode to commit node. */
        !           674:        RF_ASSERT(rdNode->numSuccedents == 1);
        !           675:        RF_ASSERT(commitNode->numAntecedents == 1);
        !           676:        rdNode->succedents[0] = commitNode;
        !           677:        commitNode->antecedents[0] = rdNode;
        !           678:        commitNode->antType[0] = rf_control;
        !           679:
        !           680:        /* Connect commit node to terminator. */
        !           681:        RF_ASSERT(commitNode->numSuccedents == 1);
        !           682:        RF_ASSERT(termNode->numAntecedents == 1);
        !           683:        RF_ASSERT(termNode->numSuccedents == 0);
        !           684:        commitNode->succedents[0] = termNode;
        !           685:        termNode->antecedents[0] = commitNode;
        !           686:        termNode->antType[0] = rf_control;
        !           687: }
        !           688:
        !           689: /*
        !           690:  * XXX move this elsewhere ?
        !           691:  */
        !           692: void
        !           693: rf_DD_GenerateFailedAccessASMs(
        !           694:     RF_Raid_t                   *raidPtr,
        !           695:     RF_AccessStripeMap_t        *asmap,
        !           696:     RF_PhysDiskAddr_t          **pdap,
        !           697:     int                                 *nNodep,
        !           698:     RF_PhysDiskAddr_t          **pqpdap,
        !           699:     int                                 *nPQNodep,
        !           700:     RF_AllocListElem_t          *allocList
        !           701: )
        !           702: {
        !           703:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !           704:        int PDAPerDisk, i;
        !           705:        RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit;
        !           706:        int numDataCol = layoutPtr->numDataCol;
        !           707:        int state;
        !           708:        RF_SectorNum_t suoff, suend;
        !           709:        unsigned firstDataCol, napdas, count;
        !           710:        RF_SectorNum_t fone_start, fone_end, ftwo_start = 0, ftwo_end = 0;
        !           711:        RF_PhysDiskAddr_t *fone = asmap->failedPDAs[0];
        !           712:        RF_PhysDiskAddr_t *ftwo = asmap->failedPDAs[1];
        !           713:        RF_PhysDiskAddr_t *pda_p;
        !           714:        RF_PhysDiskAddr_t *phys_p;
        !           715:        RF_RaidAddr_t sosAddr;
        !           716:
        !           717:        /*
        !           718:         * Determine how many pda's we will have to generate per unaccessed
        !           719:         * stripe. If there is only one failed data unit, it is one; if two,
        !           720:         * possibly two, depending whether they overlap.
        !           721:         */
        !           722:
        !           723:        fone_start = rf_StripeUnitOffset(layoutPtr, fone->startSector);
        !           724:        fone_end = fone_start + fone->numSector;
        !           725:
        !           726: #define        CONS_PDA(if,start,num)          do {                            \
        !           727:        pda_p->row = asmap->if->row;                                    \
        !           728:        pda_p->col = asmap->if->col;                                    \
        !           729:        pda_p->startSector = ((asmap->if->startSector / secPerSU) *     \
        !           730:            secPerSU) + start;                                          \
        !           731:        pda_p->numSector = num;                                         \
        !           732:        pda_p->next = NULL;                                             \
        !           733:        RF_MallocAndAdd(pda_p->bufPtr,                                  \
        !           734:            rf_RaidAddressToByte(raidPtr,num),(char *), allocList);     \
        !           735: } while (0)
        !           736:
        !           737:        if (asmap->numDataFailed == 1) {
        !           738:                PDAPerDisk = 1;
        !           739:                state = 1;
        !           740:                RF_MallocAndAdd(*pqpdap, 2 * sizeof(RF_PhysDiskAddr_t),
        !           741:                    (RF_PhysDiskAddr_t *), allocList);
        !           742:                pda_p = *pqpdap;
        !           743:                /* Build p. */
        !           744:                CONS_PDA(parityInfo, fone_start, fone->numSector);
        !           745:                pda_p->type = RF_PDA_TYPE_PARITY;
        !           746:                pda_p++;
        !           747:                /* Build q. */
        !           748:                CONS_PDA(qInfo, fone_start, fone->numSector);
        !           749:                pda_p->type = RF_PDA_TYPE_Q;
        !           750:        } else {
        !           751:                ftwo_start = rf_StripeUnitOffset(layoutPtr, ftwo->startSector);
        !           752:                ftwo_end = ftwo_start + ftwo->numSector;
        !           753:                if (fone->numSector + ftwo->numSector > secPerSU) {
        !           754:                        PDAPerDisk = 1;
        !           755:                        state = 2;
        !           756:                        RF_MallocAndAdd(*pqpdap, 2 * sizeof(RF_PhysDiskAddr_t),
        !           757:                            (RF_PhysDiskAddr_t *), allocList);
        !           758:                        pda_p = *pqpdap;
        !           759:                        CONS_PDA(parityInfo, 0, secPerSU);
        !           760:                        pda_p->type = RF_PDA_TYPE_PARITY;
        !           761:                        pda_p++;
        !           762:                        CONS_PDA(qInfo, 0, secPerSU);
        !           763:                        pda_p->type = RF_PDA_TYPE_Q;
        !           764:                } else {
        !           765:                        PDAPerDisk = 2;
        !           766:                        state = 3;
        !           767:                        /* Four of them, fone, then ftwo. */
        !           768:                        RF_MallocAndAdd(*pqpdap, 4 * sizeof(RF_PhysDiskAddr_t),
        !           769:                            (RF_PhysDiskAddr_t *), allocList);
        !           770:                        pda_p = *pqpdap;
        !           771:                        CONS_PDA(parityInfo, fone_start, fone->numSector);
        !           772:                        pda_p->type = RF_PDA_TYPE_PARITY;
        !           773:                        pda_p++;
        !           774:                        CONS_PDA(qInfo, fone_start, fone->numSector);
        !           775:                        pda_p->type = RF_PDA_TYPE_Q;
        !           776:                        pda_p++;
        !           777:                        CONS_PDA(parityInfo, ftwo_start, ftwo->numSector);
        !           778:                        pda_p->type = RF_PDA_TYPE_PARITY;
        !           779:                        pda_p++;
        !           780:                        CONS_PDA(qInfo, ftwo_start, ftwo->numSector);
        !           781:                        pda_p->type = RF_PDA_TYPE_Q;
        !           782:                }
        !           783:        }
        !           784:        /* Figure out number of nonaccessed pda. */
        !           785:        napdas = PDAPerDisk * (numDataCol - asmap->numStripeUnitsAccessed -
        !           786:            (ftwo == NULL ? 1 : 0));
        !           787:        *nPQNodep = PDAPerDisk;
        !           788:
        !           789:        /*
        !           790:         * Sweep over the over accessed pda's, figuring out the number of
        !           791:         * additional pda's to generate. Of course, skip the failed ones.
        !           792:         */
        !           793:
        !           794:        count = 0;
        !           795:        for (pda_p = asmap->physInfo; pda_p; pda_p = pda_p->next) {
        !           796:                if ((pda_p == fone) || (pda_p == ftwo))
        !           797:                        continue;
        !           798:                suoff = rf_StripeUnitOffset(layoutPtr, pda_p->startSector);
        !           799:                suend = suoff + pda_p->numSector;
        !           800:                switch (state) {
        !           801:                case 1: /* One failed PDA to overlap. */
        !           802:                        /*
        !           803:                         * If a PDA doesn't contain the failed unit, it can
        !           804:                         * only miss the start or end, not both.
        !           805:                         */
        !           806:                        if ((suoff > fone_start) || (suend < fone_end))
        !           807:                                count++;
        !           808:                        break;
        !           809:                case 2: /* Whole stripe. */
        !           810:                        if (suoff)                      /* Leak at begining. */
        !           811:                                count++;
        !           812:                        if (suend < numDataCol)         /* Leak at end. */
        !           813:                                count++;
        !           814:                        break;
        !           815:                case 3: /* Two disjoint units. */
        !           816:                        if ((suoff > fone_start) || (suend < fone_end))
        !           817:                                count++;
        !           818:                        if ((suoff > ftwo_start) || (suend < ftwo_end))
        !           819:                                count++;
        !           820:                        break;
        !           821:                default:
        !           822:                        RF_PANIC();
        !           823:                }
        !           824:        }
        !           825:
        !           826:        napdas += count;
        !           827:        *nNodep = napdas;
        !           828:        if (napdas == 0)
        !           829:                return;         /* short circuit */
        !           830:
        !           831:        /* Allocate up our list of pda's. */
        !           832:
        !           833:        RF_CallocAndAdd(pda_p, napdas, sizeof(RF_PhysDiskAddr_t),
        !           834:            (RF_PhysDiskAddr_t *), allocList);
        !           835:        *pdap = pda_p;
        !           836:
        !           837:        /* Link them together. */
        !           838:        for (i = 0; i < (napdas - 1); i++)
        !           839:                pda_p[i].next = pda_p + (i + 1);
        !           840:
        !           841:        /* March through the one's up to the first accessed disk. */
        !           842:        firstDataCol = rf_RaidAddressToStripeUnitID(&(raidPtr->Layout),
        !           843:            asmap->physInfo->raidAddress) % numDataCol;
        !           844:        sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr,
        !           845:            asmap->raidAddress);
        !           846:        for (i = 0; i < firstDataCol; i++) {
        !           847:                if ((pda_p - (*pdap)) == napdas)
        !           848:                        continue;
        !           849:                pda_p->type = RF_PDA_TYPE_DATA;
        !           850:                pda_p->raidAddress = sosAddr + (i * secPerSU);
        !           851:                (raidPtr->Layout.map->MapSector) (raidPtr, pda_p->raidAddress,
        !           852:                    &(pda_p->row), &(pda_p->col), &(pda_p->startSector), 0);
        !           853:                /* Skip over dead disks. */
        !           854:                if (RF_DEAD_DISK(raidPtr->Disks[pda_p->row][pda_p->col].status))
        !           855:                        continue;
        !           856:                switch (state) {
        !           857:                case 1: /* Fone. */
        !           858:                        pda_p->numSector = fone->numSector;
        !           859:                        pda_p->raidAddress += fone_start;
        !           860:                        pda_p->startSector += fone_start;
        !           861:                        RF_MallocAndAdd(pda_p->bufPtr,
        !           862:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !           863:                            (char *), allocList);
        !           864:                        break;
        !           865:                case 2: /* Full stripe. */
        !           866:                        pda_p->numSector = secPerSU;
        !           867:                        RF_MallocAndAdd(pda_p->bufPtr,
        !           868:                            rf_RaidAddressToByte(raidPtr, secPerSU),
        !           869:                            (char *), allocList);
        !           870:                        break;
        !           871:                case 3: /* Two slabs. */
        !           872:                        pda_p->numSector = fone->numSector;
        !           873:                        pda_p->raidAddress += fone_start;
        !           874:                        pda_p->startSector += fone_start;
        !           875:                        RF_MallocAndAdd(pda_p->bufPtr,
        !           876:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !           877:                            (char *), allocList);
        !           878:                        pda_p++;
        !           879:                        pda_p->type = RF_PDA_TYPE_DATA;
        !           880:                        pda_p->raidAddress = sosAddr + (i * secPerSU);
        !           881:                        (raidPtr->Layout.map->MapSector) (raidPtr,
        !           882:                            pda_p->raidAddress, &(pda_p->row), &(pda_p->col),
        !           883:                            &(pda_p->startSector), 0);
        !           884:                        pda_p->numSector = ftwo->numSector;
        !           885:                        pda_p->raidAddress += ftwo_start;
        !           886:                        pda_p->startSector += ftwo_start;
        !           887:                        RF_MallocAndAdd(pda_p->bufPtr,
        !           888:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !           889:                            (char *), allocList);
        !           890:                        break;
        !           891:                default:
        !           892:                        RF_PANIC();
        !           893:                }
        !           894:                pda_p++;
        !           895:        }
        !           896:
        !           897:        /* March through the touched stripe units. */
        !           898:        for (phys_p = asmap->physInfo; phys_p; phys_p = phys_p->next, i++) {
        !           899:                if ((phys_p == asmap->failedPDAs[0]) ||
        !           900:                    (phys_p == asmap->failedPDAs[1]))
        !           901:                        continue;
        !           902:                suoff = rf_StripeUnitOffset(layoutPtr, phys_p->startSector);
        !           903:                suend = suoff + phys_p->numSector;
        !           904:                switch (state) {
        !           905:                case 1: /* Single buffer. */
        !           906:                        if (suoff > fone_start) {
        !           907:                                RF_ASSERT(suend >= fone_end);
        !           908:                                /*
        !           909:                                 * The data read starts after the mapped
        !           910:                                 * access, snip off the begining.
        !           911:                                 */
        !           912:                                pda_p->numSector = suoff - fone_start;
        !           913:                                pda_p->raidAddress = sosAddr + (i * secPerSU)
        !           914:                                    + fone_start;
        !           915:                                (raidPtr->Layout.map->MapSector) (raidPtr,
        !           916:                                    pda_p->raidAddress, &(pda_p->row),
        !           917:                                    &(pda_p->col), &(pda_p->startSector), 0);
        !           918:                                RF_MallocAndAdd(pda_p->bufPtr,
        !           919:                                    rf_RaidAddressToByte(raidPtr,
        !           920:                                    pda_p->numSector), (char *), allocList);
        !           921:                                pda_p++;
        !           922:                        }
        !           923:                        if (suend < fone_end) {
        !           924:                                RF_ASSERT(suoff <= fone_start);
        !           925:                                /*
        !           926:                                 * The data read stops before the end of the
        !           927:                                 * failed access, extend.
        !           928:                                 */
        !           929:                                pda_p->numSector = fone_end - suend;
        !           930:                                pda_p->raidAddress = sosAddr + (i * secPerSU)
        !           931:                                    + suend;    /* off by one? */
        !           932:                                (raidPtr->Layout.map->MapSector) (raidPtr,
        !           933:                                    pda_p->raidAddress, &(pda_p->row),
        !           934:                                    &(pda_p->col), &(pda_p->startSector), 0);
        !           935:                                RF_MallocAndAdd(pda_p->bufPtr,
        !           936:                                    rf_RaidAddressToByte(raidPtr,
        !           937:                                    pda_p->numSector), (char *), allocList);
        !           938:                                pda_p++;
        !           939:                        }
        !           940:                        break;
        !           941:                case 2: /* Whole stripe unit. */
        !           942:                        RF_ASSERT((suoff == 0) || (suend == secPerSU));
        !           943:                        if (suend < secPerSU) {
        !           944:                                /* Short read, snip from end on. */
        !           945:                                pda_p->numSector = secPerSU - suend;
        !           946:                                pda_p->raidAddress = sosAddr + (i * secPerSU)
        !           947:                                    + suend;    /* off by one? */
        !           948:                                (raidPtr->Layout.map->MapSector) (raidPtr,
        !           949:                                    pda_p->raidAddress, &(pda_p->row),
        !           950:                                    &(pda_p->col), &(pda_p->startSector), 0);
        !           951:                                RF_MallocAndAdd(pda_p->bufPtr,
        !           952:                                    rf_RaidAddressToByte(raidPtr,
        !           953:                                    pda_p->numSector), (char *), allocList);
        !           954:                                pda_p++;
        !           955:                        } else
        !           956:                                if (suoff > 0) {
        !           957:                                        /* Short at front. */
        !           958:                                        pda_p->numSector = suoff;
        !           959:                                        pda_p->raidAddress = sosAddr +
        !           960:                                            (i * secPerSU);
        !           961:                                        (raidPtr->Layout.map->MapSector)
        !           962:                                            (raidPtr, pda_p->raidAddress,
        !           963:                                            &(pda_p->row), &(pda_p->col),
        !           964:                                            &(pda_p->startSector), 0);
        !           965:                                        RF_MallocAndAdd(pda_p->bufPtr,
        !           966:                                            rf_RaidAddressToByte(raidPtr,
        !           967:                                            pda_p->numSector), (char *),
        !           968:                                            allocList);
        !           969:                                        pda_p++;
        !           970:                                }
        !           971:                        break;
        !           972:                case 3: /* Two nonoverlapping failures. */
        !           973:                        if ((suoff > fone_start) || (suend < fone_end)) {
        !           974:                                if (suoff > fone_start) {
        !           975:                                        RF_ASSERT(suend >= fone_end);
        !           976:                                        /*
        !           977:                                         * The data read starts after the
        !           978:                                         * mapped access, snip off the
        !           979:                                         * begining.
        !           980:                                         */
        !           981:                                        pda_p->numSector = suoff - fone_start;
        !           982:                                        pda_p->raidAddress = sosAddr +
        !           983:                                            (i * secPerSU) + fone_start;
        !           984:                                        (raidPtr->Layout.map->MapSector)
        !           985:                                            (raidPtr, pda_p->raidAddress,
        !           986:                                            &(pda_p->row), &(pda_p->col),
        !           987:                                            &(pda_p->startSector), 0);
        !           988:                                        RF_MallocAndAdd(pda_p->bufPtr,
        !           989:                                            rf_RaidAddressToByte(raidPtr,
        !           990:                                            pda_p->numSector), (char *),
        !           991:                                            allocList);
        !           992:                                        pda_p++;
        !           993:                                }
        !           994:                                if (suend < fone_end) {
        !           995:                                        RF_ASSERT(suoff <= fone_start);
        !           996:                                        /*
        !           997:                                         * The data read stops before the end
        !           998:                                         * of the failed access, extend.
        !           999:                                         */
        !          1000:                                        pda_p->numSector = fone_end - suend;
        !          1001:                                        pda_p->raidAddress = sosAddr +
        !          1002:                                            (i * secPerSU) +
        !          1003:                                            suend;      /* Off by one ? */
        !          1004:                                        (raidPtr->Layout.map->MapSector)
        !          1005:                                            (raidPtr, pda_p->raidAddress,
        !          1006:                                            &(pda_p->row), &(pda_p->col),
        !          1007:                                            &(pda_p->startSector), 0);
        !          1008:                                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1009:                                            rf_RaidAddressToByte(raidPtr,
        !          1010:                                            pda_p->numSector), (char *),
        !          1011:                                            allocList);
        !          1012:                                        pda_p++;
        !          1013:                                }
        !          1014:                        }
        !          1015:                        if ((suoff > ftwo_start) || (suend < ftwo_end)) {
        !          1016:                                if (suoff > ftwo_start) {
        !          1017:                                        RF_ASSERT(suend >= ftwo_end);
        !          1018:                                        /*
        !          1019:                                         * The data read starts after the
        !          1020:                                         * mapped access, snip off the
        !          1021:                                         * begining.
        !          1022:                                         */
        !          1023:                                        pda_p->numSector = suoff - ftwo_start;
        !          1024:                                        pda_p->raidAddress = sosAddr +
        !          1025:                                            (i * secPerSU) + ftwo_start;
        !          1026:                                        (raidPtr->Layout.map->MapSector)
        !          1027:                                            (raidPtr, pda_p->raidAddress,
        !          1028:                                            &(pda_p->row), &(pda_p->col),
        !          1029:                                            &(pda_p->startSector), 0);
        !          1030:                                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1031:                                            rf_RaidAddressToByte(raidPtr,
        !          1032:                                            pda_p->numSector), (char *),
        !          1033:                                            allocList);
        !          1034:                                        pda_p++;
        !          1035:                                }
        !          1036:                                if (suend < ftwo_end) {
        !          1037:                                        RF_ASSERT(suoff <= ftwo_start);
        !          1038:                                        /*
        !          1039:                                         * The data read stops before the end
        !          1040:                                         * of the failed access, extend.
        !          1041:                                         */
        !          1042:                                        pda_p->numSector = ftwo_end - suend;
        !          1043:                                        pda_p->raidAddress = sosAddr +
        !          1044:                                            (i * secPerSU) +
        !          1045:                                            suend;      /* Off by one ? */
        !          1046:                                        (raidPtr->Layout.map->MapSector)
        !          1047:                                            (raidPtr, pda_p->raidAddress,
        !          1048:                                            &(pda_p->row), &(pda_p->col),
        !          1049:                                            &(pda_p->startSector), 0);
        !          1050:                                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1051:                                            rf_RaidAddressToByte(raidPtr,
        !          1052:                                            pda_p->numSector), (char *),
        !          1053:                                            allocList);
        !          1054:                                        pda_p++;
        !          1055:                                }
        !          1056:                        }
        !          1057:                        break;
        !          1058:                default:
        !          1059:                        RF_PANIC();
        !          1060:                }
        !          1061:        }
        !          1062:
        !          1063:        /* After the last accessed disk. */
        !          1064:        for (; i < numDataCol; i++) {
        !          1065:                if ((pda_p - (*pdap)) == napdas)
        !          1066:                        continue;
        !          1067:                pda_p->type = RF_PDA_TYPE_DATA;
        !          1068:                pda_p->raidAddress = sosAddr + (i * secPerSU);
        !          1069:                (raidPtr->Layout.map->MapSector) (raidPtr, pda_p->raidAddress,
        !          1070:                    &(pda_p->row), &(pda_p->col), &(pda_p->startSector), 0);
        !          1071:                /* Skip over dead disks. */
        !          1072:                if (RF_DEAD_DISK(raidPtr->Disks[pda_p->row][pda_p->col].status))
        !          1073:                        continue;
        !          1074:                switch (state) {
        !          1075:                case 1: /* Fone. */
        !          1076:                        pda_p->numSector = fone->numSector;
        !          1077:                        pda_p->raidAddress += fone_start;
        !          1078:                        pda_p->startSector += fone_start;
        !          1079:                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1080:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !          1081:                            (char *), allocList);
        !          1082:                        break;
        !          1083:                case 2: /* Full stripe. */
        !          1084:                        pda_p->numSector = secPerSU;
        !          1085:                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1086:                            rf_RaidAddressToByte(raidPtr, secPerSU),
        !          1087:                            (char *), allocList);
        !          1088:                        break;
        !          1089:                case 3: /* Two slabs. */
        !          1090:                        pda_p->numSector = fone->numSector;
        !          1091:                        pda_p->raidAddress += fone_start;
        !          1092:                        pda_p->startSector += fone_start;
        !          1093:                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1094:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !          1095:                            (char *), allocList);
        !          1096:                        pda_p++;
        !          1097:                        pda_p->type = RF_PDA_TYPE_DATA;
        !          1098:                        pda_p->raidAddress = sosAddr + (i * secPerSU);
        !          1099:                        (raidPtr->Layout.map->MapSector) (raidPtr,
        !          1100:                            pda_p->raidAddress, &(pda_p->row), &(pda_p->col),
        !          1101:                            &(pda_p->startSector), 0);
        !          1102:                        pda_p->numSector = ftwo->numSector;
        !          1103:                        pda_p->raidAddress += ftwo_start;
        !          1104:                        pda_p->startSector += ftwo_start;
        !          1105:                        RF_MallocAndAdd(pda_p->bufPtr,
        !          1106:                            rf_RaidAddressToByte(raidPtr, pda_p->numSector),
        !          1107:                            (char *), allocList);
        !          1108:                        break;
        !          1109:                default:
        !          1110:                        RF_PANIC();
        !          1111:                }
        !          1112:                pda_p++;
        !          1113:        }
        !          1114:
        !          1115:        RF_ASSERT(pda_p - *pdap == napdas);
        !          1116:        return;
        !          1117: }
        !          1118:
        !          1119: #define        INIT_DISK_NODE(node,name)       do {                            \
        !          1120:        rf_InitNode(node, rf_wait, RF_FALSE, rf_DiskReadFunc,           \
        !          1121:            rf_DiskReadUndoFunc, rf_GenericWakeupFunc, 2,1,4,0,         \
        !          1122:            dag_h, name, allocList);                                    \
        !          1123:        (node)->succedents[0] = unblockNode;                            \
        !          1124:        (node)->succedents[1] = recoveryNode;                           \
        !          1125:        (node)->antecedents[0] = blockNode;                             \
        !          1126:        (node)->antType[0] = rf_control;                                \
        !          1127: } while (0)
        !          1128:
        !          1129: #define        DISK_NODE_PARAMS(_node_,_p_)    do {                            \
        !          1130:        (_node_).params[0].p = _p_ ;                                    \
        !          1131:        (_node_).params[1].p = (_p_)->bufPtr;                           \
        !          1132:        (_node_).params[2].v = parityStripeID;                          \
        !          1133:        (_node_).params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,  \
        !          1134:            0, 0, which_ru);                                            \
        !          1135: } while (0)
        !          1136:
        !          1137: void
        !          1138: rf_DoubleDegRead(
        !          1139:     RF_Raid_t                   *raidPtr,
        !          1140:     RF_AccessStripeMap_t        *asmap,
        !          1141:     RF_DagHeader_t              *dag_h,
        !          1142:     void                        *bp,
        !          1143:     RF_RaidAccessFlags_t         flags,
        !          1144:     RF_AllocListElem_t          *allocList,
        !          1145:     char                        *redundantReadNodeName,
        !          1146:     char                        *recoveryNodeName,
        !          1147:     int                                (*recovFunc) (RF_DagNode_t *)
        !          1148: )
        !          1149: {
        !          1150:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !          1151:        RF_DagNode_t *nodes, *rudNodes, *rrdNodes, *recoveryNode, *blockNode,
        !          1152:            *unblockNode, *rpNodes, *rqNodes, *termNode;
        !          1153:        RF_PhysDiskAddr_t *pda, *pqPDAs;
        !          1154:        RF_PhysDiskAddr_t *npdas;
        !          1155:        int nNodes, nRrdNodes, nRudNodes, i;
        !          1156:        RF_ReconUnitNum_t which_ru;
        !          1157:        int nReadNodes, nPQNodes;
        !          1158:        RF_PhysDiskAddr_t *failedPDA = asmap->failedPDAs[0];
        !          1159:        RF_PhysDiskAddr_t *failedPDAtwo = asmap->failedPDAs[1];
        !          1160:        RF_StripeNum_t parityStripeID = rf_RaidAddressToParityStripeID(
        !          1161:            layoutPtr, asmap->raidAddress, &which_ru);
        !          1162:
        !          1163:        if (rf_dagDebug)
        !          1164:                printf("[Creating Double Degraded Read DAG]\n");
        !          1165:        rf_DD_GenerateFailedAccessASMs(raidPtr, asmap, &npdas, &nRrdNodes,
        !          1166:            &pqPDAs, &nPQNodes, allocList);
        !          1167:
        !          1168:        nRudNodes = asmap->numStripeUnitsAccessed - (asmap->numDataFailed);
        !          1169:        nReadNodes = nRrdNodes + nRudNodes + 2 * nPQNodes;
        !          1170:        nNodes = 4 /* Block, unblock, recovery, term. */ + nReadNodes;
        !          1171:
        !          1172:        RF_CallocAndAdd(nodes, nNodes, sizeof(RF_DagNode_t), (RF_DagNode_t *),
        !          1173:            allocList);
        !          1174:        i = 0;
        !          1175:        blockNode = &nodes[i];
        !          1176:        i += 1;
        !          1177:        unblockNode = &nodes[i];
        !          1178:        i += 1;
        !          1179:        recoveryNode = &nodes[i];
        !          1180:        i += 1;
        !          1181:        termNode = &nodes[i];
        !          1182:        i += 1;
        !          1183:        rudNodes = &nodes[i];
        !          1184:        i += nRudNodes;
        !          1185:        rrdNodes = &nodes[i];
        !          1186:        i += nRrdNodes;
        !          1187:        rpNodes = &nodes[i];
        !          1188:        i += nPQNodes;
        !          1189:        rqNodes = &nodes[i];
        !          1190:        i += nPQNodes;
        !          1191:        RF_ASSERT(i == nNodes);
        !          1192:
        !          1193:        dag_h->numSuccedents = 1;
        !          1194:        dag_h->succedents[0] = blockNode;
        !          1195:        dag_h->creator = "DoubleDegRead";
        !          1196:        dag_h->numCommits = 0;
        !          1197:        dag_h->numCommitNodes = 1;      /* Unblock. */
        !          1198:
        !          1199:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !          1200:            rf_TerminateUndoFunc, NULL, 0, 2, 0, 0, dag_h, "Trm", allocList);
        !          1201:        termNode->antecedents[0] = unblockNode;
        !          1202:        termNode->antType[0] = rf_control;
        !          1203:        termNode->antecedents[1] = recoveryNode;
        !          1204:        termNode->antType[1] = rf_control;
        !          1205:
        !          1206:        /*
        !          1207:         * Init the block and unblock nodes.
        !          1208:         * The block node has all nodes except itself, unblock and
        !          1209:         * recovery as successors.
        !          1210:         * Similarly for predecessors of the unblock.
        !          1211:         */
        !          1212:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !          1213:            rf_NullNodeUndoFunc, NULL, nReadNodes, 0, 0, 0, dag_h,
        !          1214:            "Nil", allocList);
        !          1215:        rf_InitNode(unblockNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !          1216:            rf_NullNodeUndoFunc, NULL, 1, nReadNodes, 0, 0, dag_h,
        !          1217:            "Nil", allocList);
        !          1218:
        !          1219:        for (i = 0; i < nReadNodes; i++) {
        !          1220:                blockNode->succedents[i] = rudNodes + i;
        !          1221:                unblockNode->antecedents[i] = rudNodes + i;
        !          1222:                unblockNode->antType[i] = rf_control;
        !          1223:        }
        !          1224:        unblockNode->succedents[0] = termNode;
        !          1225:
        !          1226:        /*
        !          1227:         * The recovery node has all the reads as predecessors, and the term
        !          1228:         * node as successors. It gets a pda as a param from each of the read
        !          1229:         * nodes plus the raidPtr. For each failed unit is has a result pda.
        !          1230:         */
        !          1231:        rf_InitNode(recoveryNode, rf_wait, RF_FALSE, recovFunc,
        !          1232:            rf_NullNodeUndoFunc, NULL,
        !          1233:            1,                          /* succesors */
        !          1234:            nReadNodes,                 /* preds */
        !          1235:            nReadNodes + 2,             /* params */
        !          1236:            asmap->numDataFailed,       /* results */
        !          1237:            dag_h, recoveryNodeName, allocList);
        !          1238:
        !          1239:        recoveryNode->succedents[0] = termNode;
        !          1240:        for (i = 0; i < nReadNodes; i++) {
        !          1241:                recoveryNode->antecedents[i] = rudNodes + i;
        !          1242:                recoveryNode->antType[i] = rf_trueData;
        !          1243:        }
        !          1244:
        !          1245:        /*
        !          1246:         * Build the read nodes, then come back and fill in recovery params
        !          1247:         * and results.
        !          1248:         */
        !          1249:        pda = asmap->physInfo;
        !          1250:        for (i = 0; i < nRudNodes; pda = pda->next) {
        !          1251:                if ((pda == failedPDA) || (pda == failedPDAtwo))
        !          1252:                        continue;
        !          1253:                INIT_DISK_NODE(rudNodes + i, "Rud");
        !          1254:                RF_ASSERT(pda);
        !          1255:                DISK_NODE_PARAMS(rudNodes[i], pda);
        !          1256:                i++;
        !          1257:        }
        !          1258:
        !          1259:        pda = npdas;
        !          1260:        for (i = 0; i < nRrdNodes; i++, pda = pda->next) {
        !          1261:                INIT_DISK_NODE(rrdNodes + i, "Rrd");
        !          1262:                RF_ASSERT(pda);
        !          1263:                DISK_NODE_PARAMS(rrdNodes[i], pda);
        !          1264:        }
        !          1265:
        !          1266:        /* Redundancy pdas. */
        !          1267:        pda = pqPDAs;
        !          1268:        INIT_DISK_NODE(rpNodes, "Rp");
        !          1269:        RF_ASSERT(pda);
        !          1270:        DISK_NODE_PARAMS(rpNodes[0], pda);
        !          1271:        pda++;
        !          1272:        INIT_DISK_NODE(rqNodes, redundantReadNodeName);
        !          1273:        RF_ASSERT(pda);
        !          1274:        DISK_NODE_PARAMS(rqNodes[0], pda);
        !          1275:        if (nPQNodes == 2) {
        !          1276:                pda++;
        !          1277:                INIT_DISK_NODE(rpNodes + 1, "Rp");
        !          1278:                RF_ASSERT(pda);
        !          1279:                DISK_NODE_PARAMS(rpNodes[1], pda);
        !          1280:                pda++;
        !          1281:                INIT_DISK_NODE(rqNodes + 1, redundantReadNodeName);
        !          1282:                RF_ASSERT(pda);
        !          1283:                DISK_NODE_PARAMS(rqNodes[1], pda);
        !          1284:        }
        !          1285:        /* Fill in recovery node params. */
        !          1286:        for (i = 0; i < nReadNodes; i++)
        !          1287:                recoveryNode->params[i] = rudNodes[i].params[0]; /* pda */
        !          1288:        recoveryNode->params[i++].p = (void *) raidPtr;
        !          1289:        recoveryNode->params[i++].p = (void *) asmap;
        !          1290:        recoveryNode->results[0] = failedPDA;
        !          1291:        if (asmap->numDataFailed == 2)
        !          1292:                recoveryNode->results[1] = failedPDAtwo;
        !          1293:
        !          1294:        /* Zero fill the target data buffers ? */
        !          1295: }

CVSweb