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

Annotation of sys/dev/raidframe/rf_raid1.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: rf_raid1.c,v 1.5 2002/12/16 07:01:04 tdeval Exp $     */
                      2: /*     $NetBSD: rf_raid1.c,v 1.5 2000/01/08 22:57:30 oster Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Carnegie-Mellon University.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Author: William V. Courtright II
                      9:  *
                     10:  * Permission to use, copy, modify and distribute this software and
                     11:  * its documentation is hereby granted, provided that both the copyright
                     12:  * notice and this permission notice appear in all copies of the
                     13:  * software, derivative works or modified versions, and any portions
                     14:  * thereof, and that both notices appear in supporting documentation.
                     15:  *
                     16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
                     18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     19:  *
                     20:  * Carnegie Mellon requests users of this software to return to
                     21:  *
                     22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     23:  *  School of Computer Science
                     24:  *  Carnegie Mellon University
                     25:  *  Pittsburgh PA 15213-3890
                     26:  *
                     27:  * any improvements or extensions that they make and grant Carnegie the
                     28:  * rights to redistribute these changes.
                     29:  */
                     30:
                     31: /*****************************************************************************
                     32:  *
                     33:  * rf_raid1.c -- Implements RAID Level 1.
                     34:  *
                     35:  *****************************************************************************/
                     36:
                     37: #include "rf_raid.h"
                     38: #include "rf_raid1.h"
                     39: #include "rf_dag.h"
                     40: #include "rf_dagffrd.h"
                     41: #include "rf_dagffwr.h"
                     42: #include "rf_dagdegrd.h"
                     43: #include "rf_dagutils.h"
                     44: #include "rf_dagfuncs.h"
                     45: #include "rf_diskqueue.h"
                     46: #include "rf_general.h"
                     47: #include "rf_utils.h"
                     48: #include "rf_parityscan.h"
                     49: #include "rf_mcpair.h"
                     50: #include "rf_layout.h"
                     51: #include "rf_map.h"
                     52: #include "rf_engine.h"
                     53: #include "rf_reconbuffer.h"
                     54:
                     55: typedef struct RF_Raid1ConfigInfo_s {
                     56:        RF_RowCol_t **stripeIdentifier;
                     57: } RF_Raid1ConfigInfo_t;
                     58:
                     59:
                     60: /* Start of day code specific to RAID level 1. */
                     61: int
                     62: rf_ConfigureRAID1(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
                     63:     RF_Config_t *cfgPtr)
                     64: {
                     65:        RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
                     66:        RF_Raid1ConfigInfo_t *info;
                     67:        RF_RowCol_t i;
                     68:
                     69:        /* Create a RAID level 1 configuration structure. */
                     70:        RF_MallocAndAdd(info, sizeof(RF_Raid1ConfigInfo_t),
                     71:            (RF_Raid1ConfigInfo_t *), raidPtr->cleanupList);
                     72:        if (info == NULL)
                     73:                return (ENOMEM);
                     74:        layoutPtr->layoutSpecificInfo = (void *) info;
                     75:
                     76:        /* ... and fill it in. */
                     77:        info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol / 2, 2,
                     78:            raidPtr->cleanupList);
                     79:        if (info->stripeIdentifier == NULL)
                     80:                return (ENOMEM);
                     81:        for (i = 0; i < (raidPtr->numCol / 2); i++) {
                     82:                info->stripeIdentifier[i][0] = (2 * i);
                     83:                info->stripeIdentifier[i][1] = (2 * i) + 1;
                     84:        }
                     85:
                     86:        RF_ASSERT(raidPtr->numRow == 1);
                     87:
                     88:        /*
                     89:         * This implementation of RAID level 1 uses one row of numCol disks
                     90:         * and allows multiple (numCol / 2) stripes per row. A stripe
                     91:         * consists of a single data unit and a single parity (mirror) unit.
                     92:         * Stripe id = raidAddr / stripeUnitSize.
                     93:         */
                     94:        raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
                     95:            (raidPtr->numCol / 2) * layoutPtr->sectorsPerStripeUnit;
                     96:        layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk *
                     97:            (raidPtr->numCol / 2);
                     98:        layoutPtr->dataSectorsPerStripe = layoutPtr->sectorsPerStripeUnit;
                     99:        layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
                    100:            raidPtr->logBytesPerSector;
                    101:        layoutPtr->numDataCol = 1;
                    102:        layoutPtr->numParityCol = 1;
                    103:        return (0);
                    104: }
                    105:
                    106:
                    107: /*
                    108:  * Returns the physical disk location of the primary copy in the mirror pair.
                    109:  */
                    110: void
                    111: rf_MapSectorRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
                    112:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
                    113: {
                    114:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
                    115:        RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
                    116:
                    117:        *row = 0;
                    118:        *col = 2 * mirrorPair;
                    119:        *diskSector = ((SUID / (raidPtr->numCol / 2)) *
                    120:             raidPtr->Layout.sectorsPerStripeUnit) +
                    121:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
                    122: }
                    123:
                    124:
                    125: /*
                    126:  * Map Parity.
                    127:  *
                    128:  * Returns the physical disk location of the secondary copy in the mirror
                    129:  * pair.
                    130:  */
                    131: void
                    132: rf_MapParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
                    133:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
                    134: {
                    135:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
                    136:        RF_RowCol_t mirrorPair = SUID % (raidPtr->numCol / 2);
                    137:
                    138:        *row = 0;
                    139:        *col = (2 * mirrorPair) + 1;
                    140:
                    141:        *diskSector = ((SUID / (raidPtr->numCol / 2)) *
                    142:             raidPtr->Layout.sectorsPerStripeUnit) +
                    143:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
                    144: }
                    145:
                    146:
                    147: /*
                    148:  * IdentifyStripeRAID1
                    149:  *
                    150:  * Returns a list of disks for a given redundancy group.
                    151:  */
                    152: void
                    153: rf_IdentifyStripeRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
                    154:     RF_RowCol_t **diskids, RF_RowCol_t *outRow)
                    155: {
                    156:        RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
                    157:            addr);
                    158:        RF_Raid1ConfigInfo_t *info = raidPtr->Layout.layoutSpecificInfo;
                    159:        RF_ASSERT(stripeID >= 0);
                    160:        RF_ASSERT(addr >= 0);
                    161:        *outRow = 0;
                    162:        *diskids = info->stripeIdentifier[stripeID % (raidPtr->numCol / 2)];
                    163:        RF_ASSERT(*diskids);
                    164: }
                    165:
                    166:
                    167: /*
                    168:  * MapSIDToPSIDRAID1
                    169:  *
                    170:  * Maps a logical stripe to a stripe in the redundant array.
                    171:  */
                    172: void
                    173: rf_MapSIDToPSIDRAID1(RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID,
                    174:     RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
                    175: {
                    176:        *which_ru = 0;
                    177:        *psID = stripeID;
                    178: }
                    179:
                    180:
                    181:
                    182: /*****************************************************************************
                    183:  * Select a graph to perform a single-stripe access.
                    184:  *
                    185:  * Parameters: raidPtr    - Description of the physical array.
                    186:  *             type       - Type of operation (read or write) requested.
                    187:  *             asmap      - Logical & physical addresses for this access.
                    188:  *             createFunc - Name of function to use to create the graph.
                    189:  *****************************************************************************/
                    190:
                    191: void
                    192: rf_RAID1DagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
                    193:     RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
                    194: {
                    195:        RF_RowCol_t frow, fcol, or, oc;
                    196:        RF_PhysDiskAddr_t *failedPDA;
                    197:        int prior_recon;
                    198:        RF_RowStatus_t rstat;
                    199:        RF_SectorNum_t oo;
                    200:
                    201:
                    202:        RF_ASSERT(RF_IO_IS_R_OR_W(type));
                    203:
                    204:        if (asmap->numDataFailed + asmap->numParityFailed > 1) {
                    205:                RF_ERRORMSG("Multiple disks failed in a single group !"
                    206:                            "  Aborting I/O operation.\n");
                    207:                *createFunc = NULL;
                    208:                return;
                    209:        }
                    210:        if (asmap->numDataFailed + asmap->numParityFailed) {
                    211:                /*
                    212:                 * We've got a fault. Re-map to spare space, iff applicable.
                    213:                 * Shouldn't the arch-independent code do this for us ?
                    214:                 * Anyway, it turns out if we don't do this here, then when
                    215:                 * we're reconstructing, writes go only to the surviving
                    216:                 * original disk, and aren't reflected on the reconstructed
                    217:                 * spare. Oops. --jimz
                    218:                 */
                    219:                failedPDA = asmap->failedPDAs[0];
                    220:                frow = failedPDA->row;
                    221:                fcol = failedPDA->col;
                    222:                rstat = raidPtr->status[frow];
                    223:                prior_recon = (rstat == rf_rs_reconfigured) || (
                    224:                    (rstat == rf_rs_reconstructing) ?
                    225:                    rf_CheckRUReconstructed(raidPtr->reconControl[frow]
                    226:                     ->reconMap, failedPDA->startSector) : 0);
                    227:                if (prior_recon) {
                    228:                        or = frow;
                    229:                        oc = fcol;
                    230:                        oo = failedPDA->startSector;
                    231:                        /*
                    232:                         * If we did distributed sparing, we'd monkey with
                    233:                         * that here.
                    234:                         * But we don't, so we'll.
                    235:                         */
                    236:                        failedPDA->row = raidPtr->Disks[frow][fcol].spareRow;
                    237:                        failedPDA->col = raidPtr->Disks[frow][fcol].spareCol;
                    238:                        /*
                    239:                         * Redirect other components, iff necessary. This looks
                    240:                         * pretty suspicious to me, but it's what the raid5
                    241:                         * DAG select does.
                    242:                         */
                    243:                        if (asmap->parityInfo->next) {
                    244:                                if (failedPDA == asmap->parityInfo) {
                    245:                                        failedPDA->next->row = failedPDA->row;
                    246:                                        failedPDA->next->col = failedPDA->col;
                    247:                                } else {
                    248:                                        if (failedPDA ==
                    249:                                            asmap->parityInfo->next) {
                    250:                                                asmap->parityInfo->row =
                    251:                                                    failedPDA->row;
                    252:                                                asmap->parityInfo->col =
                    253:                                                    failedPDA->col;
                    254:                                        }
                    255:                                }
                    256:                        }
                    257:                        if (rf_dagDebug || rf_mapDebug) {
                    258:                                printf("raid%d: Redirected type '%c' r %d c %d"
                    259:                                    " o %ld -> r %d c %d o %ld.\n",
                    260:                                    raidPtr->raidid, type, or, oc, (long) oo,
                    261:                                    failedPDA->row, failedPDA->col,
                    262:                                    (long) failedPDA->startSector);
                    263:                        }
                    264:                        asmap->numDataFailed = asmap->numParityFailed = 0;
                    265:                }
                    266:        }
                    267:        if (type == RF_IO_TYPE_READ) {
                    268:                if (asmap->numDataFailed == 0)
                    269:                        *createFunc = (RF_VoidFuncPtr)
                    270:                            rf_CreateMirrorIdleReadDAG;
                    271:                else
                    272:                        *createFunc = (RF_VoidFuncPtr)
                    273:                            rf_CreateRaidOneDegradedReadDAG;
                    274:        } else {
                    275:                *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
                    276:        }
                    277: }
                    278:
                    279: int
                    280: rf_VerifyParityRAID1(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr,
                    281:     RF_PhysDiskAddr_t *parityPDA, int correct_it, RF_RaidAccessFlags_t flags)
                    282: {
                    283:        int nbytes, bcount, stripeWidth, ret, i, j, nbad, *bbufs;
                    284:        RF_DagNode_t *blockNode, *unblockNode, *wrBlock;
                    285:        RF_DagHeader_t *rd_dag_h, *wr_dag_h;
                    286:        RF_AccessStripeMapHeader_t *asm_h;
                    287:        RF_AllocListElem_t *allocList;
                    288:        RF_AccTraceEntry_t tracerec;
                    289:        RF_ReconUnitNum_t which_ru;
                    290:        RF_RaidLayout_t *layoutPtr;
                    291:        RF_AccessStripeMap_t *aasm;
                    292:        RF_SectorCount_t nsector;
                    293:        RF_RaidAddr_t startAddr;
                    294:        char *buf, *buf1, *buf2;
                    295:        RF_PhysDiskAddr_t *pda;
                    296:        RF_StripeNum_t psID;
                    297:        RF_MCPair_t *mcpair;
                    298:
                    299:        layoutPtr = &raidPtr->Layout;
                    300:        startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
                    301:        nsector = parityPDA->numSector;
                    302:        nbytes = rf_RaidAddressToByte(raidPtr, nsector);
                    303:        psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
                    304:
                    305:        asm_h = NULL;
                    306:        rd_dag_h = wr_dag_h = NULL;
                    307:        mcpair = NULL;
                    308:
                    309:        ret = RF_PARITY_COULD_NOT_VERIFY;
                    310:
                    311:        rf_MakeAllocList(allocList);
                    312:        if (allocList == NULL)
                    313:                return (RF_PARITY_COULD_NOT_VERIFY);
                    314:        mcpair = rf_AllocMCPair();
                    315:        if (mcpair == NULL)
                    316:                goto done;
                    317:        RF_ASSERT(layoutPtr->numDataCol == layoutPtr->numParityCol);
                    318:        stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
                    319:        bcount = nbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol);
                    320:        RF_MallocAndAdd(buf, bcount, (char *), allocList);
                    321:        if (buf == NULL)
                    322:                goto done;
                    323:        if (rf_verifyParityDebug) {
                    324:                printf("raid%d: RAID1 parity verify: buf=%lx bcount=%d"
                    325:                    " (%lx - %lx).\n", raidPtr->raidid, (long) buf, bcount,
                    326:                    (long) buf, (long) buf + bcount);
                    327:        }
                    328:        /*
                    329:         * Generate a DAG that will read the entire stripe- then we can
                    330:         * just compare data chunks versus "parity" chunks.
                    331:         */
                    332:
                    333:        rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, nbytes, buf,
                    334:            rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", allocList, flags,
                    335:            RF_IO_NORMAL_PRIORITY);
                    336:        if (rd_dag_h == NULL)
                    337:                goto done;
                    338:        blockNode = rd_dag_h->succedents[0];
                    339:        unblockNode = blockNode->succedents[0]->succedents[0];
                    340:
                    341:        /*
                    342:         * Map the access to physical disk addresses (PDAs)- this will
                    343:         * get us both a list of data addresses, and "parity" addresses
                    344:         * (which are really mirror copies).
                    345:         */
                    346:        asm_h = rf_MapAccess(raidPtr, startAddr,
                    347:            layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
                    348:        aasm = asm_h->stripeMap;
                    349:
                    350:        buf1 = buf;
                    351:        /*
                    352:         * Loop through the data blocks, setting up read nodes for each.
                    353:         */
                    354:        for (pda = aasm->physInfo, i = 0; i < layoutPtr->numDataCol;
                    355:             i++, pda = pda->next) {
                    356:                RF_ASSERT(pda);
                    357:
                    358:                rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
                    359:
                    360:                RF_ASSERT(pda->numSector != 0);
                    361:                if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
                    362:                        /* cannot verify parity with dead disk */
                    363:                        goto done;
                    364:                }
                    365:                pda->bufPtr = buf1;
                    366:                blockNode->succedents[i]->params[0].p = pda;
                    367:                blockNode->succedents[i]->params[1].p = buf1;
                    368:                blockNode->succedents[i]->params[2].v = psID;
                    369:                blockNode->succedents[i]->params[3].v =
                    370:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
                    371:                buf1 += nbytes;
                    372:        }
                    373:        RF_ASSERT(pda == NULL);
                    374:        /*
                    375:         * Keep i, buf1 running.
                    376:         *
                    377:         * Loop through parity blocks, setting up read nodes for each.
                    378:         */
                    379:        for (pda = aasm->parityInfo; i < layoutPtr->numDataCol +
                    380:             layoutPtr->numParityCol; i++, pda = pda->next) {
                    381:                RF_ASSERT(pda);
                    382:                rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
                    383:                RF_ASSERT(pda->numSector != 0);
                    384:                if (rf_TryToRedirectPDA(raidPtr, pda, 0)) {
                    385:                        /* Cannot verify parity with dead disk. */
                    386:                        goto done;
                    387:                }
                    388:                pda->bufPtr = buf1;
                    389:                blockNode->succedents[i]->params[0].p = pda;
                    390:                blockNode->succedents[i]->params[1].p = buf1;
                    391:                blockNode->succedents[i]->params[2].v = psID;
                    392:                blockNode->succedents[i]->params[3].v =
                    393:                    RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
                    394:                buf1 += nbytes;
                    395:        }
                    396:        RF_ASSERT(pda == NULL);
                    397:
                    398:        bzero((char *) &tracerec, sizeof(tracerec));
                    399:        rd_dag_h->tracerec = &tracerec;
                    400:
                    401:        if (rf_verifyParityDebug > 1) {
                    402:                printf("raid%d: RAID1 parity verify read dag:\n",
                    403:                    raidPtr->raidid);
                    404:                rf_PrintDAGList(rd_dag_h);
                    405:        }
                    406:        RF_LOCK_MUTEX(mcpair->mutex);
                    407:        mcpair->flag = 0;
                    408:        rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
                    409:            (void *) mcpair);
                    410:        while (mcpair->flag == 0) {
                    411:                RF_WAIT_MCPAIR(mcpair);
                    412:        }
                    413:        RF_UNLOCK_MUTEX(mcpair->mutex);
                    414:
                    415:        if (rd_dag_h->status != rf_enable) {
                    416:                RF_ERRORMSG("Unable to verify raid1 parity:"
                    417:                            " can't read stripe.\n");
                    418:                ret = RF_PARITY_COULD_NOT_VERIFY;
                    419:                goto done;
                    420:        }
                    421:        /*
                    422:         * buf1 is the beginning of the data blocks chunk.
                    423:         * buf2 is the beginning of the parity blocks chunk.
                    424:         */
                    425:        buf1 = buf;
                    426:        buf2 = buf + (nbytes * layoutPtr->numDataCol);
                    427:        ret = RF_PARITY_OKAY;
                    428:        /*
                    429:         * bbufs is "bad bufs"- an array whose entries are the data
                    430:         * column numbers where we had miscompares. (That is, column 0
                    431:         * and column 1 of the array are mirror copies, and are considered
                    432:         * "data column 0" for this purpose).
                    433:         */
                    434:        RF_MallocAndAdd(bbufs, layoutPtr->numParityCol * sizeof(int), (int *),
                    435:            allocList);
                    436:        nbad = 0;
                    437:        /*
                    438:         * Check data vs "parity" (mirror copy).
                    439:         */
                    440:        for (i = 0; i < layoutPtr->numDataCol; i++) {
                    441:                if (rf_verifyParityDebug) {
                    442:                        printf("raid%d: RAID1 parity verify %d bytes: i=%d"
                    443:                            " buf1=%lx buf2=%lx buf=%lx.\n", raidPtr->raidid,
                    444:                            nbytes, i, (long) buf1, (long) buf2, (long) buf);
                    445:                }
                    446:                ret = bcmp(buf1, buf2, nbytes);
                    447:                if (ret) {
                    448:                        if (rf_verifyParityDebug > 1) {
                    449:                                for (j = 0; j < nbytes; j++) {
                    450:                                        if (buf1[j] != buf2[j])
                    451:                                                break;
                    452:                                }
                    453:                                printf("psid=%ld j=%d\n", (long) psID, j);
                    454:                                printf("buf1 %02x %02x %02x %02x %02x\n",
                    455:                                    buf1[0] & 0xff, buf1[1] & 0xff,
                    456:                                    buf1[2] & 0xff, buf1[3] & 0xff,
                    457:                                    buf1[4] & 0xff);
                    458:                                printf("buf2 %02x %02x %02x %02x %02x\n",
                    459:                                    buf2[0] & 0xff, buf2[1] & 0xff,
                    460:                                    buf2[2] & 0xff, buf2[3] & 0xff,
                    461:                                    buf2[4] & 0xff);
                    462:                        }
                    463:                        if (rf_verifyParityDebug) {
                    464:                                printf("raid%d: RAID1: found bad parity,"
                    465:                                    " i=%d.\n", raidPtr->raidid, i);
                    466:                        }
                    467:                        /*
                    468:                         * Parity is bad. Keep track of which columns were bad.
                    469:                         */
                    470:                        if (bbufs)
                    471:                                bbufs[nbad] = i;
                    472:                        nbad++;
                    473:                        ret = RF_PARITY_BAD;
                    474:                }
                    475:                buf1 += nbytes;
                    476:                buf2 += nbytes;
                    477:        }
                    478:
                    479:        if ((ret != RF_PARITY_OKAY) && correct_it) {
                    480:                ret = RF_PARITY_COULD_NOT_CORRECT;
                    481:                if (rf_verifyParityDebug) {
                    482:                        printf("raid%d: RAID1 parity verify:"
                    483:                            " parity not correct.\n", raidPtr->raidid);
                    484:                }
                    485:                if (bbufs == NULL)
                    486:                        goto done;
                    487:                /*
                    488:                 * Make a DAG with one write node for each bad unit. We'll
                    489:                 * simply write the contents of the data unit onto the parity
                    490:                 * unit for correction. (It's possible that the mirror copy
                    491:                 * was the correct copy, and that we're spooging good data by
                    492:                 * writing bad over it, but there's no way we can know that.
                    493:                 */
                    494:                wr_dag_h = rf_MakeSimpleDAG(raidPtr, nbad, nbytes, buf,
                    495:                    rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", allocList,
                    496:                    flags, RF_IO_NORMAL_PRIORITY);
                    497:                if (wr_dag_h == NULL)
                    498:                        goto done;
                    499:                wrBlock = wr_dag_h->succedents[0];
                    500:                /*
                    501:                 * Fill in a write node for each bad compare.
                    502:                 */
                    503:                for (i = 0; i < nbad; i++) {
                    504:                        j = i + layoutPtr->numDataCol;
                    505:                        pda = blockNode->succedents[j]->params[0].p;
                    506:                        pda->bufPtr = blockNode->succedents[i]->params[1].p;
                    507:                        wrBlock->succedents[i]->params[0].p = pda;
                    508:                        wrBlock->succedents[i]->params[1].p = pda->bufPtr;
                    509:                        wrBlock->succedents[i]->params[2].v = psID;
                    510:                        wrBlock->succedents[0]->params[3].v =
                    511:                            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0,
                    512:                             which_ru);
                    513:                }
                    514:                bzero((char *) &tracerec, sizeof(tracerec));
                    515:                wr_dag_h->tracerec = &tracerec;
                    516:                if (rf_verifyParityDebug > 1) {
                    517:                        printf("Parity verify write dag:\n");
                    518:                        rf_PrintDAGList(wr_dag_h);
                    519:                }
                    520:                RF_LOCK_MUTEX(mcpair->mutex);
                    521:                mcpair->flag = 0;
                    522:                /* Fire off the write DAG. */
                    523:                rf_DispatchDAG(wr_dag_h, (void (*) (void *))
                    524:                    rf_MCPairWakeupFunc, (void *) mcpair);
                    525:                while (!mcpair->flag) {
                    526:                        RF_WAIT_COND(mcpair->cond, mcpair->mutex);
                    527:                }
                    528:                RF_UNLOCK_MUTEX(mcpair->mutex);
                    529:                if (wr_dag_h->status != rf_enable) {
                    530:                        RF_ERRORMSG("Unable to correct RAID1 parity in"
                    531:                                    " VerifyParity.\n");
                    532:                        goto done;
                    533:                }
                    534:                ret = RF_PARITY_CORRECTED;
                    535:        }
                    536: done:
                    537:        /*
                    538:         * All done. We might've gotten here without doing part of the function,
                    539:         * so cleanup what we have to and return our running status.
                    540:         */
                    541:        if (asm_h)
                    542:                rf_FreeAccessStripeMap(asm_h);
                    543:        if (rd_dag_h)
                    544:                rf_FreeDAG(rd_dag_h);
                    545:        if (wr_dag_h)
                    546:                rf_FreeDAG(wr_dag_h);
                    547:        if (mcpair)
                    548:                rf_FreeMCPair(mcpair);
                    549:        rf_FreeAllocList(allocList);
                    550:        if (rf_verifyParityDebug) {
                    551:                printf("raid%d: RAID1 parity verify, returning %d.\n",
                    552:                    raidPtr->raidid, ret);
                    553:        }
                    554:        return (ret);
                    555: }
                    556:
                    557: int
                    558: rf_SubmitReconBufferRAID1(
                    559:     RF_ReconBuffer_t   *rbuf,          /* The recon buffer to submit. */
                    560:     int                         keep_it,       /*
                    561:                                         * Whether we can keep this buffer
                    562:                                         * or we have to return it ?
                    563:                                         */
                    564:     int                         use_committed  /*
                    565:                                         * Whether to use a committed or
                    566:                                         * an available recon buffer ?
                    567:                                         */
                    568: )
                    569: {
                    570:        RF_ReconParityStripeStatus_t *pssPtr;
                    571:        RF_ReconCtrl_t *reconCtrlPtr;
                    572:        RF_RaidLayout_t *layoutPtr;
                    573:        int retcode, created;
                    574:        RF_CallbackDesc_t *cb, *p;
                    575:        RF_ReconBuffer_t *t;
                    576:        RF_Raid_t *raidPtr;
                    577:        caddr_t ta;
                    578:
                    579:        retcode = 0;
                    580:        created = 0;
                    581:
                    582:        raidPtr = rbuf->raidPtr;
                    583:        layoutPtr = &raidPtr->Layout;
                    584:        reconCtrlPtr = raidPtr->reconControl[rbuf->row];
                    585:
                    586:        RF_ASSERT(rbuf);
                    587:        RF_ASSERT(rbuf->col != reconCtrlPtr->fcol);
                    588:
                    589:        if (rf_reconbufferDebug) {
                    590:                printf("raid%d: RAID1 reconbuffer submission r%d c%d psid %ld"
                    591:                    " ru%d (failed offset %ld).\n", raidPtr->raidid, rbuf->row,
                    592:                    rbuf->col, (long) rbuf->parityStripeID, rbuf->which_ru,
                    593:                    (long) rbuf->failedDiskSectorOffset);
                    594:        }
                    595:        if (rf_reconDebug) {
                    596:                printf("RAID1 reconbuffer submit psid %ld buf %lx\n",
                    597:                    (long) rbuf->parityStripeID, (long) rbuf->buffer);
                    598:                printf("RAID1 psid %ld   %02x %02x %02x %02x %02x\n",
                    599:                    (long) rbuf->parityStripeID,
                    600:                    rbuf->buffer[0], rbuf->buffer[1], rbuf->buffer[2],
                    601:                    rbuf->buffer[3], rbuf->buffer[4]);
                    602:        }
                    603:        RF_LOCK_PSS_MUTEX(raidPtr, rbuf->row, rbuf->parityStripeID);
                    604:
                    605:        RF_LOCK_MUTEX(reconCtrlPtr->rb_mutex);
                    606:
                    607:        pssPtr = rf_LookupRUStatus(raidPtr, reconCtrlPtr->pssTable,
                    608:            rbuf->parityStripeID, rbuf->which_ru, RF_PSS_NONE, &created);
                    609:        RF_ASSERT(pssPtr);      /*
                    610:                                 * If it didn't exist, we wouldn't have gotten
                    611:                                 * an rbuf for it.
                    612:                                 */
                    613:
                    614:        /*
                    615:         * Since this is simple mirroring, the first submission for a stripe
                    616:         * is also treated as the last.
                    617:         */
                    618:
                    619:        t = NULL;
                    620:        if (keep_it) {
                    621:                if (rf_reconbufferDebug) {
                    622:                        printf("raid%d: RAID1 rbuf submission: keeping rbuf.\n",
                    623:                            raidPtr->raidid);
                    624:                }
                    625:                t = rbuf;
                    626:        } else {
                    627:                if (use_committed) {
                    628:                        if (rf_reconbufferDebug) {
                    629:                                printf("raid%d: RAID1 rbuf submission:"
                    630:                                    " using committed rbuf.\n",
                    631:                                    raidPtr->raidid);
                    632:                        }
                    633:                        t = reconCtrlPtr->committedRbufs;
                    634:                        RF_ASSERT(t);
                    635:                        reconCtrlPtr->committedRbufs = t->next;
                    636:                        t->next = NULL;
                    637:                } else
                    638:                        if (reconCtrlPtr->floatingRbufs) {
                    639:                                if (rf_reconbufferDebug) {
                    640:                                        printf("raid%d: RAID1 rbuf submission:"
                    641:                                            " using floating rbuf.\n",
                    642:                                            raidPtr->raidid);
                    643:                                }
                    644:                                t = reconCtrlPtr->floatingRbufs;
                    645:                                reconCtrlPtr->floatingRbufs = t->next;
                    646:                                t->next = NULL;
                    647:                        }
                    648:        }
                    649:        if (t == NULL) {
                    650:                if (rf_reconbufferDebug) {
                    651:                        printf("raid%d: RAID1 rbuf submission:"
                    652:                            " waiting for rbuf.\n", raidPtr->raidid);
                    653:                }
                    654:                RF_ASSERT((keep_it == 0) && (use_committed == 0));
                    655:                raidPtr->procsInBufWait++;
                    656:                if ((raidPtr->procsInBufWait == (raidPtr->numCol - 1))
                    657:                    && (raidPtr->numFullReconBuffers == 0)) {
                    658:                        /* ruh-ro */
                    659:                        RF_ERRORMSG("Buffer wait deadlock.\n");
                    660:                        rf_PrintPSStatusTable(raidPtr, rbuf->row);
                    661:                        RF_PANIC();
                    662:                }
                    663:                pssPtr->flags |= RF_PSS_BUFFERWAIT;
                    664:                cb = rf_AllocCallbackDesc();
                    665:                cb->row = rbuf->row;
                    666:                cb->col = rbuf->col;
                    667:                cb->callbackArg.v = rbuf->parityStripeID;
                    668:                cb->callbackArg2.v = rbuf->which_ru;
                    669:                cb->next = NULL;
                    670:                if (reconCtrlPtr->bufferWaitList == NULL) {
                    671:                        /* We are the wait list- lucky us. */
                    672:                        reconCtrlPtr->bufferWaitList = cb;
                    673:                } else {
                    674:                        /* Append to wait list. */
                    675:                        for (p = reconCtrlPtr->bufferWaitList; p->next;
                    676:                             p = p->next);
                    677:                        p->next = cb;
                    678:                }
                    679:                retcode = 1;
                    680:                goto out;
                    681:        }
                    682:        if (t != rbuf) {
                    683:                t->row = rbuf->row;
                    684:                t->col = reconCtrlPtr->fcol;
                    685:                t->parityStripeID = rbuf->parityStripeID;
                    686:                t->which_ru = rbuf->which_ru;
                    687:                t->failedDiskSectorOffset = rbuf->failedDiskSectorOffset;
                    688:                t->spRow = rbuf->spRow;
                    689:                t->spCol = rbuf->spCol;
                    690:                t->spOffset = rbuf->spOffset;
                    691:                /* Swap buffers. DANCE ! */
                    692:                ta = t->buffer;
                    693:                t->buffer = rbuf->buffer;
                    694:                rbuf->buffer = ta;
                    695:        }
                    696:        /*
                    697:         * Use the rbuf we've been given as the target.
                    698:         */
                    699:        RF_ASSERT(pssPtr->rbuf == NULL);
                    700:        pssPtr->rbuf = t;
                    701:
                    702:        t->count = 1;
                    703:        /*
                    704:         * Below, we use 1 for numDataCol (which is equal to the count in the
                    705:         * previous line), so we'll always be done.
                    706:         */
                    707:        rf_CheckForFullRbuf(raidPtr, reconCtrlPtr, pssPtr, 1);
                    708:
                    709: out:
                    710:        RF_UNLOCK_PSS_MUTEX(raidPtr, rbuf->row, rbuf->parityStripeID);
                    711:        RF_UNLOCK_MUTEX(reconCtrlPtr->rb_mutex);
                    712:        if (rf_reconbufferDebug) {
                    713:                printf("raid%d: RAID1 rbuf submission: returning %d.\n",
                    714:                    raidPtr->raidid, retcode);
                    715:        }
                    716:        return (retcode);
                    717: }

CVSweb