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

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

1.1     ! nbrk        1: /*     $OpenBSD: rf_evenodd.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $   */
        !             2: /*     $NetBSD: rf_evenodd.c,v 1.4 2000/01/07 03:40:59 oster Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Chang-Ming Wu
        !             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_evenodd.c -- implements EVENODD array architecture
        !            34:  *
        !            35:  *****************************************************************************/
        !            36:
        !            37: #include "rf_archs.h"
        !            38:
        !            39: #if    RF_INCLUDE_EVENODD > 0
        !            40:
        !            41: #include "rf_types.h"
        !            42: #include "rf_raid.h"
        !            43: #include "rf_dag.h"
        !            44: #include "rf_dagffrd.h"
        !            45: #include "rf_dagffwr.h"
        !            46: #include "rf_dagdegrd.h"
        !            47: #include "rf_dagdegwr.h"
        !            48: #include "rf_dagutils.h"
        !            49: #include "rf_dagfuncs.h"
        !            50: #include "rf_etimer.h"
        !            51: #include "rf_general.h"
        !            52: #include "rf_evenodd.h"
        !            53: #include "rf_configure.h"
        !            54: #include "rf_parityscan.h"
        !            55: #include "rf_utils.h"
        !            56: #include "rf_map.h"
        !            57: #include "rf_pq.h"
        !            58: #include "rf_mcpair.h"
        !            59: #include "rf_evenodd.h"
        !            60: #include "rf_evenodd_dagfuncs.h"
        !            61: #include "rf_evenodd_dags.h"
        !            62: #include "rf_engine.h"
        !            63:
        !            64: typedef struct RF_EvenOddConfigInfo_s {
        !            65:        RF_RowCol_t **stripeIdentifier; /*
        !            66:                                         * Filled in at config time & used by
        !            67:                                         * IdentifyStripe.
        !            68:                                         */
        !            69: }      RF_EvenOddConfigInfo_t;
        !            70:
        !            71: int
        !            72: rf_ConfigureEvenOdd(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
        !            73:     RF_Config_t *cfgPtr)
        !            74: {
        !            75:        RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
        !            76:        RF_EvenOddConfigInfo_t *info;
        !            77:        RF_RowCol_t i, j, startdisk;
        !            78:
        !            79:        RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t),
        !            80:            (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
        !            81:        layoutPtr->layoutSpecificInfo = (void *) info;
        !            82:
        !            83:        RF_ASSERT(raidPtr->numRow == 1);
        !            84:
        !            85:        info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol,
        !            86:            raidPtr->numCol, raidPtr->cleanupList);
        !            87:        startdisk = 0;
        !            88:        for (i = 0; i < raidPtr->numCol; i++) {
        !            89:                for (j = 0; j < raidPtr->numCol; j++) {
        !            90:                        info->stripeIdentifier[i][j] = (startdisk + j) %
        !            91:                            raidPtr->numCol;
        !            92:                }
        !            93:                if ((startdisk -= 2) < 0)
        !            94:                        startdisk += raidPtr->numCol;
        !            95:        }
        !            96:
        !            97:        /* Fill in the remaining layout parameters. */
        !            98:        layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
        !            99:        layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
        !           100:            raidPtr->logBytesPerSector;
        !           101:        layoutPtr->numDataCol = raidPtr->numCol - 2;    /*
        !           102:                                                         * ORIG:
        !           103:                                                         * layoutPtr->numDataCol
        !           104:                                                         * = raidPtr->numCol-1;
        !           105:                                                         */
        !           106: #if    RF_EO_MATRIX_DIM > 17
        !           107:        if (raidPtr->numCol <= 17) {
        !           108:                printf("Number of stripe units in a parity stripe is smaller"
        !           109:                    " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
        !           110:                    " file rf_evenodd_dagfuncs.h to\nbe 17 to increase"
        !           111:                    " performance.\n");
        !           112:                return (EINVAL);
        !           113:        }
        !           114: #elif  RF_EO_MATRIX_DIM == 17
        !           115:        if (raidPtr->numCol > 17) {
        !           116:                printf("Number of stripe units in a parity stripe is bigger"
        !           117:                    " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
        !           118:                    " file rf_evenodd_dagfuncs.h to\nbe 257 for encoding and"
        !           119:                    " decoding functions to work.\n");
        !           120:                return (EINVAL);
        !           121:        }
        !           122: #endif
        !           123:        layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
        !           124:            layoutPtr->sectorsPerStripeUnit;
        !           125:        layoutPtr->numParityCol = 2;
        !           126:        layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
        !           127:        raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
        !           128:            layoutPtr->sectorsPerStripeUnit;
        !           129:
        !           130:        raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
        !           131:            layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
        !           132:
        !           133:        return (0);
        !           134: }
        !           135:
        !           136: int
        !           137: rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr)
        !           138: {
        !           139:        return (20);
        !           140: }
        !           141:
        !           142: RF_HeadSepLimit_t
        !           143: rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr)
        !           144: {
        !           145:        return (10);
        !           146: }
        !           147:
        !           148: void
        !           149: rf_IdentifyStripeEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
        !           150:     RF_RowCol_t **diskids, RF_RowCol_t *outRow)
        !           151: {
        !           152:        RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
        !           153:            addr);
        !           154:        RF_EvenOddConfigInfo_t *info =
        !           155:            (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
        !           156:
        !           157:        *outRow = 0;
        !           158:        *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
        !           159: }
        !           160:
        !           161:
        !           162: /*
        !           163:  * The layout of stripe unit on the disks are: c0 c1 c2 c3 c4
        !           164:  *
        !           165:  *                                              0  1  2  E  P
        !           166:  *                                              5  E  P  3  4
        !           167:  *                                              P  6  7  8  E
        !           168:  *                                             10 11  E  P  9
        !           169:  *                                              E  P 12 13 14
        !           170:  *                                             ....
        !           171:  *
        !           172:  * We use the MapSectorRAID5 to map data information because the routine can
        !           173:  * be shown to map exactly the layout of data stripe unit as shown above,
        !           174:  * although we have 2 redundant information now.
        !           175:  * But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are
        !           176:  * different method from raid-5.
        !           177:  */
        !           178:
        !           179:
        !           180: void
        !           181: rf_MapParityEvenOdd(
        !           182:     RF_Raid_t          *raidPtr,
        !           183:     RF_RaidAddr_t       raidSector,
        !           184:     RF_RowCol_t                *row,
        !           185:     RF_RowCol_t                *col,
        !           186:     RF_SectorNum_t     *diskSector,
        !           187:     int                         remap
        !           188: )
        !           189: {
        !           190:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
        !           191:        RF_StripeNum_t endSUIDofthisStrip =
        !           192:            (SUID / raidPtr->Layout.numDataCol + 1) *
        !           193:            raidPtr->Layout.numDataCol - 1;
        !           194:
        !           195:        *row = 0;
        !           196:        *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
        !           197:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
        !           198:            raidPtr->Layout.sectorsPerStripeUnit +
        !           199:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
        !           200: }
        !           201:
        !           202: void
        !           203: rf_MapEEvenOdd(
        !           204:     RF_Raid_t          *raidPtr,
        !           205:     RF_RaidAddr_t       raidSector,
        !           206:     RF_RowCol_t                *row,
        !           207:     RF_RowCol_t                *col,
        !           208:     RF_SectorNum_t     *diskSector,
        !           209:     int                         remap
        !           210: )
        !           211: {
        !           212:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
        !           213:        RF_StripeNum_t endSUIDofthisStrip =
        !           214:            (SUID / raidPtr->Layout.numDataCol + 1) *
        !           215:            raidPtr->Layout.numDataCol - 1;
        !           216:
        !           217:        *row = 0;
        !           218:        *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
        !           219:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
        !           220:            raidPtr->Layout.sectorsPerStripeUnit +
        !           221:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
        !           222: }
        !           223:
        !           224: void
        !           225: rf_EODagSelect(
        !           226:     RF_Raid_t          *raidPtr,
        !           227:     RF_IoType_t                 type,
        !           228:     RF_AccessStripeMap_t *asmap,
        !           229:     RF_VoidFuncPtr     *createFunc
        !           230: )
        !           231: {
        !           232:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !           233:        unsigned ndfail = asmap->numDataFailed;
        !           234:        unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
        !           235:        unsigned ntfail = npfail + ndfail;
        !           236:
        !           237:        RF_ASSERT(RF_IO_IS_R_OR_W(type));
        !           238:        if (ntfail > 2) {
        !           239:                RF_ERRORMSG("more than two disks failed in a single group !"
        !           240:                    "  Aborting I/O operation.\n");
        !           241:                 /* *infoFunc = */ *createFunc = NULL;
        !           242:                return;
        !           243:        }
        !           244:        /* Ok, we can do this I/O. */
        !           245:        if (type == RF_IO_TYPE_READ) {
        !           246:                switch (ndfail) {
        !           247:                case 0:
        !           248:                        /* Fault free read. */
        !           249:                        *createFunc = (RF_VoidFuncPtr)
        !           250:                            rf_CreateFaultFreeReadDAG;  /* Same as raid 5. */
        !           251:                        break;
        !           252:                case 1:
        !           253:                        /* Lost a single data unit. */
        !           254:                        /*
        !           255:                         * Two cases:
        !           256:                         * (1) Parity is not lost. Do a normal raid 5
        !           257:                         * reconstruct read.
        !           258:                         * (2) Parity is lost. Do a reconstruct read using "e".
        !           259:                         */
        !           260:                        if (ntfail == 2) {      /* Also lost redundancy. */
        !           261:                                if (asmap->failedPDAs[1]->type ==
        !           262:                                    RF_PDA_TYPE_PARITY)
        !           263:                                        *createFunc = (RF_VoidFuncPtr)
        !           264:                                            rf_EO_110_CreateReadDAG;
        !           265:                                else
        !           266:                                        *createFunc = (RF_VoidFuncPtr)
        !           267:                                            rf_EO_101_CreateReadDAG;
        !           268:                        } else {
        !           269:                                /*
        !           270:                                 * P and E are ok. But is there a failure in
        !           271:                                 * some unaccessed data unit ?
        !           272:                                 */
        !           273:                                if (rf_NumFailedDataUnitsInStripe(raidPtr,
        !           274:                                    asmap) == 2)
        !           275:                                        *createFunc = (RF_VoidFuncPtr)
        !           276:                                            rf_EO_200_CreateReadDAG;
        !           277:                                else
        !           278:                                        *createFunc = (RF_VoidFuncPtr)
        !           279:                                            rf_EO_100_CreateReadDAG;
        !           280:                        }
        !           281:                        break;
        !           282:                case 2:
        !           283:                        /* *createFunc = rf_EO_200_CreateReadDAG; */
        !           284:                        *createFunc = NULL;
        !           285:                        break;
        !           286:                }
        !           287:                return;
        !           288:        }
        !           289:        /* A write. */
        !           290:        switch (ntfail) {
        !           291:        case 0:         /* Fault free. */
        !           292:                if (rf_suppressLocksAndLargeWrites ||
        !           293:                    (((asmap->numStripeUnitsAccessed <=
        !           294:                       (layoutPtr->numDataCol / 2)) &&
        !           295:                      (layoutPtr->numDataCol != 1)) ||
        !           296:                     (asmap->parityInfo->next != NULL) ||
        !           297:                     (asmap->qInfo->next != NULL) ||
        !           298:                     rf_CheckStripeForFailures(raidPtr, asmap))) {
        !           299:
        !           300:                        *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
        !           301:                } else {
        !           302:                        *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
        !           303:                }
        !           304:                break;
        !           305:
        !           306:        case 1:         /* Single disk fault. */
        !           307:                if (npfail == 1) {
        !           308:                        RF_ASSERT((asmap->failedPDAs[0]->type ==
        !           309:                            RF_PDA_TYPE_PARITY) ||
        !           310:                            (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
        !           311:                        if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {
        !           312:                                /*
        !           313:                                 * q died, treat like normal mode raid5
        !           314:                                 * write.
        !           315:                                 */
        !           316:                                if (((asmap->numStripeUnitsAccessed <=
        !           317:                                      (layoutPtr->numDataCol / 2)) ||
        !           318:                                     (asmap->numStripeUnitsAccessed == 1)) ||
        !           319:                                    (asmap->parityInfo->next != NULL) ||
        !           320:                                    rf_NumFailedDataUnitsInStripe(raidPtr,
        !           321:                                     asmap))
        !           322:                                        *createFunc = (RF_VoidFuncPtr)
        !           323:                                            rf_EO_001_CreateSmallWriteDAG;
        !           324:                                else
        !           325:                                        *createFunc = (RF_VoidFuncPtr)
        !           326:                                            rf_EO_001_CreateLargeWriteDAG;
        !           327:                        } else {
        !           328:                                /* Parity died, small write only updating Q. */
        !           329:                                if (((asmap->numStripeUnitsAccessed <=
        !           330:                                      (layoutPtr->numDataCol / 2)) ||
        !           331:                                     (asmap->numStripeUnitsAccessed == 1)) ||
        !           332:                                    (asmap->qInfo->next != NULL) ||
        !           333:                                    rf_NumFailedDataUnitsInStripe(raidPtr,
        !           334:                                     asmap))
        !           335:                                        *createFunc = (RF_VoidFuncPtr)
        !           336:                                            rf_EO_010_CreateSmallWriteDAG;
        !           337:                                else
        !           338:                                        *createFunc = (RF_VoidFuncPtr)
        !           339:                                            rf_EO_010_CreateLargeWriteDAG;
        !           340:                        }
        !           341:                } else {        /*
        !           342:                                 * Data missing. Do a P reconstruct write if
        !           343:                                 * only a single data unit is lost in the
        !           344:                                 * stripe, otherwise a reconstruct write which
        !           345:                                 * is employing both P and E units.
        !           346:                                 */
        !           347:                        if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
        !           348:                        {
        !           349:                                if (asmap->numStripeUnitsAccessed == 1)
        !           350:                                        *createFunc = (RF_VoidFuncPtr)
        !           351:                                            rf_EO_200_CreateWriteDAG;
        !           352:                                else
        !           353:                                        /*
        !           354:                                         * No direct support for this case now,
        !           355:                                         * like that in Raid-5.
        !           356:                                         */
        !           357:                                        *createFunc = NULL;
        !           358:                        } else {
        !           359:                                if (asmap->numStripeUnitsAccessed != 1 &&
        !           360:                                    asmap->failedPDAs[0]->numSector !=
        !           361:                                    layoutPtr->sectorsPerStripeUnit)
        !           362:                                        /*
        !           363:                                         * No direct support for this case now,
        !           364:                                         * like that in Raid-5.
        !           365:                                         */
        !           366:                                        *createFunc = NULL;
        !           367:                                else
        !           368:                                        *createFunc = (RF_VoidFuncPtr)
        !           369:                                            rf_EO_100_CreateWriteDAG;
        !           370:                        }
        !           371:                }
        !           372:                break;
        !           373:
        !           374:        case 2:         /* Two disk faults. */
        !           375:                switch (npfail) {
        !           376:                case 2: /* Both p and q dead. */
        !           377:                        *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
        !           378:                        break;
        !           379:                case 1: /* Either p or q and dead data. */
        !           380:                        RF_ASSERT(asmap->failedPDAs[0]->type ==
        !           381:                            RF_PDA_TYPE_DATA);
        !           382:                        RF_ASSERT((asmap->failedPDAs[1]->type ==
        !           383:                            RF_PDA_TYPE_PARITY) ||
        !           384:                            (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
        !           385:                        if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
        !           386:                                if (asmap->numStripeUnitsAccessed != 1 &&
        !           387:                                    asmap->failedPDAs[0]->numSector !=
        !           388:                                    layoutPtr->sectorsPerStripeUnit)
        !           389:                                        /*
        !           390:                                         * In both PQ and EvenOdd, no direct
        !           391:                                         * support for this case now, like that
        !           392:                                         * in Raid-5.
        !           393:                                         */
        !           394:                                        *createFunc = NULL;
        !           395:                                else
        !           396:                                        *createFunc = (RF_VoidFuncPtr)
        !           397:                                            rf_EO_101_CreateWriteDAG;
        !           398:                        } else {
        !           399:                                if (asmap->numStripeUnitsAccessed != 1 &&
        !           400:                                    asmap->failedPDAs[0]->numSector !=
        !           401:                                    layoutPtr->sectorsPerStripeUnit)
        !           402:                                        /*
        !           403:                                         * No direct support for this case,
        !           404:                                         * like that in Raid-5.
        !           405:                                         */
        !           406:                                        *createFunc = NULL;
        !           407:                                else
        !           408:                                        *createFunc = (RF_VoidFuncPtr)
        !           409:                                            rf_EO_110_CreateWriteDAG;
        !           410:                        }
        !           411:                        break;
        !           412:                case 0: /* Double data loss. */
        !           413:                        /*
        !           414:                         * if(asmap->failedPDAs[0]->numSector +
        !           415:                         * asmap->failedPDAs[1]->numSector == 2 *
        !           416:                         * layoutPtr->sectorsPerStripeUnit ) createFunc =
        !           417:                         * rf_EOCreateLargeWriteDAG; else
        !           418:                         */
        !           419:                        *createFunc = NULL;     /*
        !           420:                                                 * Currently, in Evenodd, no
        !           421:                                                 * support for simultaneous
        !           422:                                                 * access of both failed SUs.
        !           423:                                                 */
        !           424:                        break;
        !           425:                }
        !           426:                break;
        !           427:
        !           428:        default:        /* More than 2 disk faults. */
        !           429:                *createFunc = NULL;
        !           430:                RF_PANIC();
        !           431:        }
        !           432:        return;
        !           433: }
        !           434:
        !           435:
        !           436: int
        !           437: rf_VerifyParityEvenOdd(
        !           438:        RF_Raid_t               *raidPtr,
        !           439:        RF_RaidAddr_t            raidAddr,
        !           440:        RF_PhysDiskAddr_t       *parityPDA,
        !           441:        int                      correct_it,
        !           442:        RF_RaidAccessFlags_t     flags
        !           443: )
        !           444: {
        !           445:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !           446:        RF_RaidAddr_t startAddr =
        !           447:            rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
        !           448:        RF_SectorCount_t numsector = parityPDA->numSector;
        !           449:        int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
        !           450:        int bytesPerStripe = numbytes * layoutPtr->numDataCol;
        !           451:        RF_DagHeader_t *rd_dag_h, *wr_dag_h;    /* Read, write dag. */
        !           452:        RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
        !           453:        RF_AccessStripeMapHeader_t *asm_h;
        !           454:        RF_AccessStripeMap_t *asmap;
        !           455:        RF_AllocListElem_t *alloclist;
        !           456:        RF_PhysDiskAddr_t *pda;
        !           457:        char *pbuf, *buf, *end_p, *p;
        !           458:        char *redundantbuf2;
        !           459:        int redundantTwoErr = 0, redundantOneErr = 0;
        !           460:        int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
        !           461:            parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
        !           462:        int i, retcode;
        !           463:        RF_ReconUnitNum_t which_ru;
        !           464:        RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr,
        !           465:            raidAddr, &which_ru);
        !           466:        int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
        !           467:        RF_AccTraceEntry_t tracerec;
        !           468:        RF_MCPair_t *mcpair;
        !           469:
        !           470:        retcode = RF_PARITY_OKAY;
        !           471:
        !           472:        mcpair = rf_AllocMCPair();
        !           473:        rf_MakeAllocList(alloclist);
        !           474:        RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol +
        !           475:            layoutPtr->numParityCol), (char *), alloclist);
        !           476:        /* Use calloc to make sure buffer is zeroed. */
        !           477:        RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
        !           478:        end_p = buf + bytesPerStripe;
        !           479:        /* Use calloc to make sure buffer is zeroed. */
        !           480:        RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);
        !           481:
        !           482:        rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf,
        !           483:            rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", alloclist, flags,
        !           484:            RF_IO_NORMAL_PRIORITY);
        !           485:        blockNode = rd_dag_h->succedents[0];
        !           486:        unblockNode = blockNode->succedents[0]->succedents[0];
        !           487:
        !           488:        /* Map the stripe and fill in the PDAs in the dag. */
        !           489:        asm_h = rf_MapAccess(raidPtr, startAddr,
        !           490:            layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
        !           491:        asmap = asm_h->stripeMap;
        !           492:
        !           493:        for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol;
        !           494:             i++, pda = pda->next) {
        !           495:                RF_ASSERT(pda);
        !           496:                rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
        !           497:                RF_ASSERT(pda->numSector != 0);
        !           498:                if (rf_TryToRedirectPDA(raidPtr, pda, 0))
        !           499:                        /*
        !           500:                         * No way to verify parity if disk is dead.
        !           501:                         * Return w/ good status.
        !           502:                         */
        !           503:                        goto out;
        !           504:                blockNode->succedents[i]->params[0].p = pda;
        !           505:                blockNode->succedents[i]->params[2].v = psID;
        !           506:                blockNode->succedents[i]->params[3].v =
        !           507:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           508:        }
        !           509:
        !           510:        RF_ASSERT(!asmap->parityInfo->next);
        !           511:        rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
        !           512:        RF_ASSERT(asmap->parityInfo->numSector != 0);
        !           513:        if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
        !           514:                goto out;
        !           515:        blockNode->succedents[layoutPtr->numDataCol]->params[0].p =
        !           516:            asmap->parityInfo;
        !           517:
        !           518:        RF_ASSERT(!asmap->qInfo->next);
        !           519:        rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
        !           520:        RF_ASSERT(asmap->qInfo->numSector != 0);
        !           521:        if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
        !           522:                goto out;
        !           523:        /*
        !           524:         * If disk is dead, b/c no reconstruction is implemented right now,
        !           525:         * the function "rf_TryToRedirectPDA" always return one, which causes
        !           526:         * go to out and return w/ good status.
        !           527:         */
        !           528:        blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p =
        !           529:            asmap->qInfo;
        !           530:
        !           531:        /* Fire off the DAG. */
        !           532:        bzero((char *) &tracerec, sizeof(tracerec));
        !           533:        rd_dag_h->tracerec = &tracerec;
        !           534:
        !           535:        if (rf_verifyParityDebug) {
        !           536:                printf("Parity verify read dag:\n");
        !           537:                rf_PrintDAGList(rd_dag_h);
        !           538:        }
        !           539:        RF_LOCK_MUTEX(mcpair->mutex);
        !           540:        mcpair->flag = 0;
        !           541:        rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           542:            (void *) mcpair);
        !           543:        while (!mcpair->flag)
        !           544:                RF_WAIT_COND(mcpair->cond, mcpair->mutex);
        !           545:        RF_UNLOCK_MUTEX(mcpair->mutex);
        !           546:        if (rd_dag_h->status != rf_enable) {
        !           547:                RF_ERRORMSG("Unable to verify parity:  can't read"
        !           548:                    " the stripe\n");
        !           549:                retcode = RF_PARITY_COULD_NOT_VERIFY;
        !           550:                goto out;
        !           551:        }
        !           552:        for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
        !           553:                rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2,
        !           554:                    redundantbuf2, numsector);
        !           555:                /*
        !           556:                 * The corresponding columns in EvenOdd encoding Matrix for
        !           557:                 * these p pointers that point to the databuffer in a full
        !           558:                 * stripe are sequential from 0 to layoutPtr->numDataCol-1.
        !           559:                 */
        !           560:                rf_bxor(p, pbuf, numbytes, NULL);
        !           561:        }
        !           562:        RF_ASSERT(i == layoutPtr->numDataCol);
        !           563:
        !           564:        for (i = 0; i < numbytes; i++) {
        !           565:                if (pbuf[i] != buf[bytesPerStripe + i]) {
        !           566:                        if (!correct_it) {
        !           567:                                RF_ERRORMSG3("Parity verify error: byte %d of"
        !           568:                                    " parity is 0x%x should be 0x%x\n", i,
        !           569:                                    (u_char) buf[bytesPerStripe + i],
        !           570:                                    (u_char) pbuf[i]);
        !           571:                        }
        !           572:                }
        !           573:                redundantOneErr = 1;
        !           574:                break;
        !           575:        }
        !           576:
        !           577:        for (i = 0; i < numbytes; i++) {
        !           578:                if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
        !           579:                        if (!correct_it) {
        !           580:                                RF_ERRORMSG3("Parity verify error: byte %d of"
        !           581:                                    " second redundant information is 0x%x"
        !           582:                                    " should be 0x%x\n", i,
        !           583:                                    (u_char) buf[bytesPerStripe + numbytes + i],
        !           584:                                    (u_char) redundantbuf2[i]);
        !           585:                        }
        !           586:                        redundantTwoErr = 1;
        !           587:                        break;
        !           588:                }
        !           589:        }
        !           590:        if (redundantOneErr || redundantTwoErr)
        !           591:                retcode = RF_PARITY_BAD;
        !           592:
        !           593:        /* Correct the first redundant disk, ie parity if it is error. */
        !           594:        if (redundantOneErr && correct_it) {
        !           595:                wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf,
        !           596:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", alloclist,
        !           597:                    flags, RF_IO_NORMAL_PRIORITY);
        !           598:                wrBlock = wr_dag_h->succedents[0];
        !           599:                wrUnblock = wrBlock->succedents[0]->succedents[0];
        !           600:                wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
        !           601:                wrBlock->succedents[0]->params[2].v = psID;
        !           602:                wrBlock->succedents[0]->params[3].v =
        !           603:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           604:                bzero((char *) &tracerec, sizeof(tracerec));
        !           605:                wr_dag_h->tracerec = &tracerec;
        !           606:                if (rf_verifyParityDebug) {
        !           607:                        printf("Parity verify write dag:\n");
        !           608:                        rf_PrintDAGList(wr_dag_h);
        !           609:                }
        !           610:                RF_LOCK_MUTEX(mcpair->mutex);
        !           611:                mcpair->flag = 0;
        !           612:                rf_DispatchDAG(wr_dag_h,
        !           613:                    (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
        !           614:                while (!mcpair->flag)
        !           615:                        RF_WAIT_COND(mcpair->cond, mcpair->mutex);
        !           616:                RF_UNLOCK_MUTEX(mcpair->mutex);
        !           617:                if (wr_dag_h->status != rf_enable) {
        !           618:                        RF_ERRORMSG("Unable to correct parity in VerifyParity:"
        !           619:                            " can't write the stripe\n");
        !           620:                        parity_cant_correct = RF_TRUE;
        !           621:                } else {
        !           622:                        parity_corrected = RF_TRUE;
        !           623:                }
        !           624:                rf_FreeDAG(wr_dag_h);
        !           625:        }
        !           626:        if (redundantTwoErr && correct_it) {
        !           627:                wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes,
        !           628:                    redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
        !           629:                    "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
        !           630:                wrBlock = wr_dag_h->succedents[0];
        !           631:                wrUnblock = wrBlock->succedents[0]->succedents[0];
        !           632:                wrBlock->succedents[0]->params[0].p = asmap->qInfo;
        !           633:                wrBlock->succedents[0]->params[2].v = psID;
        !           634:                wrBlock->succedents[0]->params[3].v =
        !           635:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
        !           636:                bzero((char *) &tracerec, sizeof(tracerec));
        !           637:                wr_dag_h->tracerec = &tracerec;
        !           638:                if (rf_verifyParityDebug) {
        !           639:                        printf("Dag of write new second redundant information"
        !           640:                            " in parity verify :\n");
        !           641:                        rf_PrintDAGList(wr_dag_h);
        !           642:                }
        !           643:                RF_LOCK_MUTEX(mcpair->mutex);
        !           644:                mcpair->flag = 0;
        !           645:                rf_DispatchDAG(wr_dag_h,
        !           646:                    (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
        !           647:                while (!mcpair->flag)
        !           648:                        RF_WAIT_COND(mcpair->cond, mcpair->mutex);
        !           649:                RF_UNLOCK_MUTEX(mcpair->mutex);
        !           650:                if (wr_dag_h->status != rf_enable) {
        !           651:                        RF_ERRORMSG("Unable to correct second redundant"
        !           652:                            " information in VerifyParity: can't write the"
        !           653:                            " stripe\n");
        !           654:                        red2_cant_correct = RF_TRUE;
        !           655:                } else {
        !           656:                        red2_corrected = RF_TRUE;
        !           657:                }
        !           658:                rf_FreeDAG(wr_dag_h);
        !           659:        }
        !           660:        if ((redundantOneErr && parity_cant_correct) ||
        !           661:            (redundantTwoErr && red2_cant_correct))
        !           662:                retcode = RF_PARITY_COULD_NOT_CORRECT;
        !           663:        if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
        !           664:                retcode = RF_PARITY_CORRECTED;
        !           665:
        !           666:
        !           667: out:
        !           668:        rf_FreeAccessStripeMap(asm_h);
        !           669:        rf_FreeAllocList(alloclist);
        !           670:        rf_FreeDAG(rd_dag_h);
        !           671:        rf_FreeMCPair(mcpair);
        !           672:        return (retcode);
        !           673: }
        !           674: #endif /* RF_INCLUDE_EVENODD > 0 */

CVSweb