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

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

1.1     ! nbrk        1: /*     $OpenBSD: rf_parityscan.c,v 1.7 2002/12/16 07:01:04 tdeval Exp $        */
        !             2: /*     $NetBSD: rf_parityscan.c,v 1.9 2000/05/28 03:00:31 oster Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Mark Holland
        !             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:  *
        !            33:  * rf_parityscan.c -- Misc utilities related to parity verification.
        !            34:  *
        !            35:  *****************************************************************************/
        !            36:
        !            37: #include "rf_types.h"
        !            38: #include "rf_raid.h"
        !            39: #include "rf_dag.h"
        !            40: #include "rf_dagfuncs.h"
        !            41: #include "rf_dagutils.h"
        !            42: #include "rf_mcpair.h"
        !            43: #include "rf_general.h"
        !            44: #include "rf_engine.h"
        !            45: #include "rf_parityscan.h"
        !            46: #include "rf_map.h"
        !            47:
        !            48:
        !            49: /*****************************************************************************
        !            50:  *
        !            51:  * Walk through the entire arry and write new parity.
        !            52:  * This works by creating two DAGs, one to read a stripe of data and one to
        !            53:  * write new parity. The first is executed, the data is xored together, and
        !            54:  * then the second is executed. To avoid constantly building and tearing down
        !            55:  * the DAGs, we create them a priori and fill them in with the mapping
        !            56:  * information as we go along.
        !            57:  *
        !            58:  * There should never be more than one thread running this.
        !            59:  *
        !            60:  *****************************************************************************/
        !            61: int
        !            62: rf_RewriteParity(RF_Raid_t *raidPtr)
        !            63: {
        !            64:        RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
        !            65:        RF_AccessStripeMapHeader_t *asm_h;
        !            66:        int ret_val;
        !            67:        int rc;
        !            68:        RF_PhysDiskAddr_t pda;
        !            69:        RF_SectorNum_t i;
        !            70:
        !            71:        if (raidPtr->Layout.map->faultsTolerated == 0) {
        !            72:                /* There isn't any parity. Call it "okay." */
        !            73:                return (RF_PARITY_OKAY);
        !            74:        }
        !            75:        if (raidPtr->status[0] != rf_rs_optimal) {
        !            76:                /*
        !            77:                 * We're in degraded mode. Don't try to verify parity now !
        !            78:                 * XXX: This should be a "we don't want to", not a
        !            79:                 * "we can't" error.
        !            80:                 */
        !            81:                return (RF_PARITY_COULD_NOT_VERIFY);
        !            82:        }
        !            83:
        !            84:        ret_val = 0;
        !            85:
        !            86:        pda.startSector = 0;
        !            87:        pda.numSector = raidPtr->Layout.sectorsPerStripeUnit;
        !            88:        rc = RF_PARITY_OKAY;
        !            89:
        !            90:        for (i = 0; i < raidPtr->totalSectors && rc <= RF_PARITY_CORRECTED;
        !            91:             i += layoutPtr->dataSectorsPerStripe) {
        !            92:                if (raidPtr->waitShutdown) {
        !            93:                        /*
        !            94:                         * Someone is pulling the plug on this set...
        !            95:                         * Abort the re-write.
        !            96:                         */
        !            97:                        return (1);
        !            98:                }
        !            99:                asm_h = rf_MapAccess(raidPtr, i,
        !           100:                    layoutPtr->dataSectorsPerStripe, NULL, RF_DONT_REMAP);
        !           101:                raidPtr->parity_rewrite_stripes_done =
        !           102:                        i / layoutPtr->dataSectorsPerStripe ;
        !           103:                rc = rf_VerifyParity(raidPtr, asm_h->stripeMap, 1, 0);
        !           104:                switch (rc) {
        !           105:                case RF_PARITY_OKAY:
        !           106:                case RF_PARITY_CORRECTED:
        !           107:                        break;
        !           108:                case RF_PARITY_BAD:
        !           109:                        printf("Parity bad during correction.\n");
        !           110:                        ret_val = 1;
        !           111:                        break;
        !           112:                case RF_PARITY_COULD_NOT_CORRECT:
        !           113:                        printf("Could not correct bad parity.\n");
        !           114:                        ret_val = 1;
        !           115:                        break;
        !           116:                case RF_PARITY_COULD_NOT_VERIFY:
        !           117:                        printf("Could not verify parity.\n");
        !           118:                        ret_val = 1;
        !           119:                        break;
        !           120:                default:
        !           121:                        printf("Bad rc=%d from VerifyParity in"
        !           122:                            " RewriteParity.\n", rc);
        !           123:                        ret_val = 1;
        !           124:                }
        !           125:                rf_FreeAccessStripeMap(asm_h);
        !           126:        }
        !           127:        return (ret_val);
        !           128: }
        !           129:
        !           130:
        !           131: /*****************************************************************************
        !           132:  *
        !           133:  * Verify that the parity in a particular stripe is correct.
        !           134:  * We validate only the range of parity defined by parityPDA, since
        !           135:  * this is all we have locked. The way we do this is to create an asm
        !           136:  * that maps the whole stripe and then range-restrict it to the parity
        !           137:  * region defined by the parityPDA.
        !           138:  *
        !           139:  *****************************************************************************/
        !           140: int
        !           141: rf_VerifyParity(RF_Raid_t *raidPtr, RF_AccessStripeMap_t *aasm, int correct_it,
        !           142:     RF_RaidAccessFlags_t flags)
        !           143: {
        !           144:        RF_PhysDiskAddr_t *parityPDA;
        !           145:        RF_AccessStripeMap_t *doasm;
        !           146:        RF_LayoutSW_t *lp;
        !           147:        int lrc, rc;
        !           148:
        !           149:        lp = raidPtr->Layout.map;
        !           150:        if (lp->faultsTolerated == 0) {
        !           151:                /*
        !           152:                 * There isn't any parity. Call it "okay."
        !           153:                 */
        !           154:                return (RF_PARITY_OKAY);
        !           155:        }
        !           156:        rc = RF_PARITY_OKAY;
        !           157:        if (lp->VerifyParity) {
        !           158:                for (doasm = aasm; doasm; doasm = doasm->next) {
        !           159:                        for (parityPDA = doasm->parityInfo; parityPDA;
        !           160:                             parityPDA = parityPDA->next) {
        !           161:                                lrc = lp->VerifyParity(raidPtr,
        !           162:                                    doasm->raidAddress, parityPDA, correct_it,
        !           163:                                    flags);
        !           164:                                if (lrc > rc) {
        !           165:                                        /*
        !           166:                                         * see rf_parityscan.h for why this
        !           167:                                         * works.
        !           168:                                         */
        !           169:                                        rc = lrc;
        !           170:                                }
        !           171:                        }
        !           172:                }
        !           173:        } else {
        !           174:                rc = RF_PARITY_COULD_NOT_VERIFY;
        !           175:        }
        !           176:        return (rc);
        !           177: }
        !           178:
        !           179: int
        !           180: rf_VerifyParityBasic(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr,
        !           181:     RF_PhysDiskAddr_t *parityPDA, int correct_it, RF_RaidAccessFlags_t flags)
        !           182: {
        !           183:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !           184:        RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr,
        !           185:            raidAddr);
        !           186:        RF_SectorCount_t numsector = parityPDA->numSector;
        !           187:        int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
        !           188:        int bytesPerStripe = numbytes * layoutPtr->numDataCol;
        !           189:        RF_DagHeader_t *rd_dag_h, *wr_dag_h;    /* Read, write dag. */
        !           190:        RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
        !           191:        RF_AccessStripeMapHeader_t *asm_h;
        !           192:        RF_AccessStripeMap_t *asmap;
        !           193:        RF_AllocListElem_t *alloclist;
        !           194:        RF_PhysDiskAddr_t *pda;
        !           195:        char *pbuf, *buf, *end_p, *p;
        !           196:        int i, retcode;
        !           197:        RF_ReconUnitNum_t which_ru;
        !           198:        RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr,
        !           199:            raidAddr, &which_ru);
        !           200:        int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
        !           201:        RF_AccTraceEntry_t tracerec;
        !           202:        RF_MCPair_t *mcpair;
        !           203:
        !           204:        retcode = RF_PARITY_OKAY;
        !           205:
        !           206:        mcpair = rf_AllocMCPair();
        !           207:        rf_MakeAllocList(alloclist);
        !           208:        RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol +
        !           209:            layoutPtr->numParityCol), (char *), alloclist);
        !           210:        /* Use calloc to make sure buffer is zeroed. */
        !           211:        RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
        !           212:        end_p = buf + bytesPerStripe;
        !           213:
        !           214:        rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf,
        !           215:            rf_DiskReadFunc, rf_DiskReadUndoFunc,
        !           216:            "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
        !           217:        blockNode = rd_dag_h->succedents[0];
        !           218:        unblockNode = blockNode->succedents[0]->succedents[0];
        !           219:
        !           220:        /* Map the stripe and fill in the PDAs in the dag. */
        !           221:        asm_h = rf_MapAccess(raidPtr, startAddr,
        !           222:            layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
        !           223:        asmap = asm_h->stripeMap;
        !           224:
        !           225:        for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol;
        !           226:             i++, pda = pda->next) {
        !           227:                RF_ASSERT(pda);
        !           228:                rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
        !           229:                RF_ASSERT(pda->numSector != 0);
        !           230:                if (rf_TryToRedirectPDA(raidPtr, pda, 0))
        !           231:                        goto out;       /*
        !           232:                                         * No way to verify parity if disk is
        !           233:                                         * dead. Return w/ good status.
        !           234:                                         */
        !           235:                blockNode->succedents[i]->params[0].p = pda;
        !           236:                blockNode->succedents[i]->params[2].v = psID;
        !           237:                blockNode->succedents[i]->params[3].v =
        !           238:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           239:        }
        !           240:
        !           241:        RF_ASSERT(!asmap->parityInfo->next);
        !           242:        rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
        !           243:        RF_ASSERT(asmap->parityInfo->numSector != 0);
        !           244:        if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
        !           245:                goto out;
        !           246:        blockNode->succedents[layoutPtr->numDataCol]->params[0].p =
        !           247:            asmap->parityInfo;
        !           248:
        !           249:        /* Fire off the DAG. */
        !           250:        bzero((char *) &tracerec, sizeof(tracerec));
        !           251:        rd_dag_h->tracerec = &tracerec;
        !           252:
        !           253:        if (rf_verifyParityDebug) {
        !           254:                printf("Parity verify read dag:\n");
        !           255:                rf_PrintDAGList(rd_dag_h);
        !           256:        }
        !           257:        RF_LOCK_MUTEX(mcpair->mutex);
        !           258:        mcpair->flag = 0;
        !           259:        rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           260:            (void *) mcpair);
        !           261:        while (!mcpair->flag)
        !           262:                RF_WAIT_COND(mcpair->cond, mcpair->mutex);
        !           263:        RF_UNLOCK_MUTEX(mcpair->mutex);
        !           264:        if (rd_dag_h->status != rf_enable) {
        !           265:                RF_ERRORMSG("Unable to verify parity:  can't read the"
        !           266:                            " stripe.\n");
        !           267:                retcode = RF_PARITY_COULD_NOT_VERIFY;
        !           268:                goto out;
        !           269:        }
        !           270:        for (p = buf; p < end_p; p += numbytes) {
        !           271:                rf_bxor(p, pbuf, numbytes, NULL);
        !           272:        }
        !           273:        for (i = 0; i < numbytes; i++) {
        !           274: #if 0
        !           275:                if (pbuf[i] != 0 || buf[bytesPerStripe + i] != 0) {
        !           276:                        printf("Bytes: %d %d %d\n", i, pbuf[i],
        !           277:                            buf[bytesPerStripe + i]);
        !           278:                }
        !           279: #endif
        !           280:                if (pbuf[i] != buf[bytesPerStripe + i]) {
        !           281:                        if (!correct_it)
        !           282:                                RF_ERRORMSG3("Parity verify error: byte %d of"
        !           283:                                    " parity is 0x%x should be 0x%x.\n", i,
        !           284:                                    (u_char) buf[bytesPerStripe + i],
        !           285:                                    (u_char) pbuf[i]);
        !           286:                        retcode = RF_PARITY_BAD;
        !           287:                        break;
        !           288:                }
        !           289:        }
        !           290:
        !           291:        if (retcode && correct_it) {
        !           292:                wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf,
        !           293:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !           294:                    "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY);
        !           295:                wrBlock = wr_dag_h->succedents[0];
        !           296:                wrUnblock = wrBlock->succedents[0]->succedents[0];
        !           297:                wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
        !           298:                wrBlock->succedents[0]->params[2].v = psID;
        !           299:                wrBlock->succedents[0]->params[3].v =
        !           300:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           301:                bzero((char *) &tracerec, sizeof(tracerec));
        !           302:                wr_dag_h->tracerec = &tracerec;
        !           303:                if (rf_verifyParityDebug) {
        !           304:                        printf("Parity verify write dag:\n");
        !           305:                        rf_PrintDAGList(wr_dag_h);
        !           306:                }
        !           307:                RF_LOCK_MUTEX(mcpair->mutex);
        !           308:                mcpair->flag = 0;
        !           309:                rf_DispatchDAG(wr_dag_h, (void (*) (void *))
        !           310:                    rf_MCPairWakeupFunc, (void *) mcpair);
        !           311:                while (!mcpair->flag)
        !           312:                        RF_WAIT_COND(mcpair->cond, mcpair->mutex);
        !           313:                RF_UNLOCK_MUTEX(mcpair->mutex);
        !           314:                if (wr_dag_h->status != rf_enable) {
        !           315:                        RF_ERRORMSG("Unable to correct parity in VerifyParity:"
        !           316:                            "  can't write the stripe.\n");
        !           317:                        retcode = RF_PARITY_COULD_NOT_CORRECT;
        !           318:                }
        !           319:                rf_FreeDAG(wr_dag_h);
        !           320:                if (retcode == RF_PARITY_BAD)
        !           321:                        retcode = RF_PARITY_CORRECTED;
        !           322:        }
        !           323: out:
        !           324:        rf_FreeAccessStripeMap(asm_h);
        !           325:        rf_FreeAllocList(alloclist);
        !           326:        rf_FreeDAG(rd_dag_h);
        !           327:        rf_FreeMCPair(mcpair);
        !           328:        return (retcode);
        !           329: }
        !           330:
        !           331: int
        !           332: rf_TryToRedirectPDA(RF_Raid_t *raidPtr, RF_PhysDiskAddr_t *pda, int parity)
        !           333: {
        !           334:        if (raidPtr->Disks[pda->row][pda->col].status == rf_ds_reconstructing) {
        !           335:                if (rf_CheckRUReconstructed(raidPtr->reconControl[pda->row]
        !           336:                     ->reconMap, pda->startSector)) {
        !           337:                        if (raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) {
        !           338:                                RF_RowCol_t or = pda->row, oc = pda->col;
        !           339:                                RF_SectorNum_t os = pda->startSector;
        !           340:                                if (parity) {
        !           341:                                        (raidPtr->Layout.map->MapParity)
        !           342:                                            (raidPtr, pda->raidAddress,
        !           343:                                             &pda->row, &pda->col,
        !           344:                                             &pda->startSector, RF_REMAP);
        !           345:                                        if (rf_verifyParityDebug)
        !           346:                                                printf("VerifyParity: Redir P"
        !           347:                                                    " r %d c %d sect %ld ->"
        !           348:                                                    " r %d c %d sect %ld.\n",
        !           349:                                                    or, oc, (long) os,
        !           350:                                                    pda->row, pda->col,
        !           351:                                                    (long) pda->startSector);
        !           352:                                } else {
        !           353:                                        (raidPtr->Layout.map->MapSector)
        !           354:                                            (raidPtr, pda->raidAddress,
        !           355:                                             &pda->row, &pda->col,
        !           356:                                             &pda->startSector, RF_REMAP);
        !           357:                                        if (rf_verifyParityDebug)
        !           358:                                                printf("VerifyParity: Redir D"
        !           359:                                                    " r %d c %d sect %ld ->"
        !           360:                                                    " r %d c %d sect %ld.\n",
        !           361:                                                    or, oc, (long) os,
        !           362:                                                    pda->row, pda->col,
        !           363:                                                    (long) pda->startSector);
        !           364:                                }
        !           365:                        } else {
        !           366:                                RF_RowCol_t spRow =
        !           367:                                    raidPtr->Disks[pda->row][pda->col].spareRow;
        !           368:                                RF_RowCol_t spCol =
        !           369:                                    raidPtr->Disks[pda->row][pda->col].spareCol;
        !           370:                                pda->row = spRow;
        !           371:                                pda->col = spCol;
        !           372:                        }
        !           373:                }
        !           374:        }
        !           375:        if (RF_DEAD_DISK(raidPtr->Disks[pda->row][pda->col].status))
        !           376:                return (1);
        !           377:        return (0);
        !           378: }
        !           379:
        !           380:
        !           381: /*****************************************************************************
        !           382:  *
        !           383:  * Currently a stub.
        !           384:  *
        !           385:  * Takes as input an ASM describing a write operation and containing one
        !           386:  * failure, and verifies that the parity was correctly updated to reflect the
        !           387:  * write.
        !           388:  *
        !           389:  * If it's a data unit that has failed, we read the other data units in the
        !           390:  * stripe and the parity unit, XOR them together, and verify that we get the
        !           391:  * data intended for the failed disk. Since it's easy, we also validate that
        !           392:  * the right data got written to the surviving data disks.
        !           393:  *
        !           394:  * If it's the parity that failed, there's really no validation we can do
        !           395:  * except the above verification that the right data got written to all disks.
        !           396:  * This is because the new data intended for the failed disk is supplied in
        !           397:  * the ASM, but this is of course not the case for the new parity.
        !           398:  *
        !           399:  *****************************************************************************/
        !           400: int
        !           401: rf_VerifyDegrModeWrite(RF_Raid_t *raidPtr, RF_AccessStripeMapHeader_t *asmh)
        !           402: {
        !           403:        return (0);
        !           404: }
        !           405:
        !           406:
        !           407: /*
        !           408:  * Creates a simple DAG with a header, a block-recon node at level 1,
        !           409:  * nNodes nodes at level 2, an unblock-recon node at level 3, and
        !           410:  * a terminator node at level 4. The stripe address field in
        !           411:  * the block and unblock nodes are not touched, nor are the pda
        !           412:  * fields in the second-level nodes, so they must be filled in later.
        !           413:  *
        !           414:  * Commit point is established at unblock node - this means that any
        !           415:  * failure during dag execution causes the dag to fail.
        !           416:  */
        !           417: RF_DagHeader_t *
        !           418: rf_MakeSimpleDAG(RF_Raid_t *raidPtr, int nNodes, int bytesPerSU, char *databuf,
        !           419:     int (*doFunc) (RF_DagNode_t * node), int (*undoFunc) (RF_DagNode_t * node),
        !           420:     char *name /* Node names at the second level. */,
        !           421:     RF_AllocListElem_t *alloclist, RF_RaidAccessFlags_t flags, int priority)
        !           422: {
        !           423:        RF_DagHeader_t *dag_h;
        !           424:        RF_DagNode_t *nodes, *termNode, *blockNode, *unblockNode;
        !           425:        int i;
        !           426:
        !           427:        /*
        !           428:         * Create the nodes, the block & unblock nodes, and the terminator
        !           429:         * node.
        !           430:         */
        !           431:        RF_CallocAndAdd(nodes, nNodes + 3, sizeof(RF_DagNode_t),
        !           432:            (RF_DagNode_t *), alloclist);
        !           433:        blockNode = &nodes[nNodes];
        !           434:        unblockNode = blockNode + 1;
        !           435:        termNode = unblockNode + 1;
        !           436:
        !           437:        dag_h = rf_AllocDAGHeader();
        !           438:        dag_h->raidPtr = (void *) raidPtr;
        !           439:        dag_h->allocList = NULL;        /* We won't use this alloc list. */
        !           440:        dag_h->status = rf_enable;
        !           441:        dag_h->numSuccedents = 1;
        !           442:        dag_h->creator = "SimpleDAG";
        !           443:
        !           444:        /*
        !           445:         * This dag can not commit until the unblock node is reached.
        !           446:         * Errors prior to the commit point imply the dag has failed.
        !           447:         */
        !           448:        dag_h->numCommitNodes = 1;
        !           449:        dag_h->numCommits = 0;
        !           450:
        !           451:        dag_h->succedents[0] = blockNode;
        !           452:        rf_InitNode(blockNode, rf_wait, RF_FALSE, rf_NullNodeFunc,
        !           453:            rf_NullNodeUndoFunc, NULL, nNodes, 0, 0, 0, dag_h,
        !           454:            "Nil", alloclist);
        !           455:        rf_InitNode(unblockNode, rf_wait, RF_TRUE, rf_NullNodeFunc,
        !           456:            rf_NullNodeUndoFunc, NULL, 1, nNodes, 0, 0, dag_h,
        !           457:            "Nil", alloclist);
        !           458:        unblockNode->succedents[0] = termNode;
        !           459:        for (i = 0; i < nNodes; i++) {
        !           460:                blockNode->succedents[i] = unblockNode->antecedents[i]
        !           461:                                         = &nodes[i];
        !           462:                unblockNode->antType[i] = rf_control;
        !           463:                rf_InitNode(&nodes[i], rf_wait, RF_FALSE, doFunc, undoFunc,
        !           464:                    rf_GenericWakeupFunc, 1, 1, 4, 0, dag_h, name, alloclist);
        !           465:                nodes[i].succedents[0] = unblockNode;
        !           466:                nodes[i].antecedents[0] = blockNode;
        !           467:                nodes[i].antType[0] = rf_control;
        !           468:                nodes[i].params[1].p = (databuf + (i * bytesPerSU));
        !           469:        }
        !           470:        rf_InitNode(termNode, rf_wait, RF_FALSE, rf_TerminateFunc,
        !           471:            rf_TerminateUndoFunc, NULL, 0, 1, 0, 0, dag_h, "Trm", alloclist);
        !           472:        termNode->antecedents[0] = unblockNode;
        !           473:        termNode->antType[0] = rf_control;
        !           474:        return (dag_h);
        !           475: }

CVSweb