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

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

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

CVSweb