[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

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