diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-01-11 14:29:56 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-01-11 14:29:56 +0000 |
commit | 5a29b52d01b420bb61a3112d2d44740a0fa99601 (patch) | |
tree | 7d6238740f53a56f5c76ba8256c785b13caaa24a /sys/dev/raidframe/rf_evenodd.c | |
parent | 799a3ea9a9c07e091f5f4e62273c6f105cf86191 (diff) |
Import of CMU's RAIDframe via NetBSD.
Diffstat (limited to 'sys/dev/raidframe/rf_evenodd.c')
-rw-r--r-- | sys/dev/raidframe/rf_evenodd.c | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/sys/dev/raidframe/rf_evenodd.c b/sys/dev/raidframe/rf_evenodd.c new file mode 100644 index 00000000000..90d18653cda --- /dev/null +++ b/sys/dev/raidframe/rf_evenodd.c @@ -0,0 +1,556 @@ +/* $OpenBSD: rf_evenodd.c,v 1.1 1999/01/11 14:29:21 niklas Exp $ */ +/* $NetBSD: rf_evenodd.c,v 1.1 1998/11/13 04:20:29 oster Exp $ */ +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chang-Ming Wu + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/***************************************************************************************** + * + * rf_evenodd.c -- implements EVENODD array architecture + * + ****************************************************************************************/ + +#include "rf_archs.h" + +#if RF_INCLUDE_EVENODD > 0 + +#include "rf_types.h" +#include "rf_raid.h" +#include "rf_dag.h" +#include "rf_dagffrd.h" +#include "rf_dagffwr.h" +#include "rf_dagdegrd.h" +#include "rf_dagdegwr.h" +#include "rf_dagutils.h" +#include "rf_dagfuncs.h" +#include "rf_threadid.h" +#include "rf_etimer.h" +#include "rf_general.h" +#include "rf_evenodd.h" +#include "rf_configure.h" +#include "rf_parityscan.h" +#include "rf_utils.h" +#include "rf_map.h" +#include "rf_pq.h" +#include "rf_mcpair.h" +#include "rf_sys.h" +#include "rf_evenodd.h" +#include "rf_evenodd_dagfuncs.h" +#include "rf_evenodd_dags.h" +#include "rf_engine.h" + +typedef struct RF_EvenOddConfigInfo_s { + RF_RowCol_t **stripeIdentifier; /* filled in at config time & used by IdentifyStripe */ +} RF_EvenOddConfigInfo_t; + +int rf_ConfigureEvenOdd(listp, raidPtr, cfgPtr) + RF_ShutdownList_t **listp; + RF_Raid_t *raidPtr; + RF_Config_t *cfgPtr; +{ + RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; + RF_EvenOddConfigInfo_t *info; + RF_RowCol_t i, j, startdisk; + + RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList); + layoutPtr->layoutSpecificInfo = (void *) info; + + RF_ASSERT(raidPtr->numRow == 1); + + info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList); + startdisk = 0; + for (i=0; i<raidPtr->numCol; i++) { + for (j=0; j<raidPtr->numCol; j++) { + info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol; + } + if ((startdisk -= 2) < 0) startdisk += raidPtr->numCol; + } + + /* fill in the remaining layout parameters */ + layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk; + layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector; + layoutPtr->numDataCol = raidPtr->numCol-2; /* ORIG: layoutPtr->numDataCol = raidPtr->numCol-1; */ +#if RF_EO_MATRIX_DIM > 17 + if (raidPtr->numCol <= 17){ + printf("Number of stripe units in a parity stripe is smaller than 17. Please\n"); + printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n"); + printf("be 17 to increase performance. \n"); + return(EINVAL); + } +#elif RF_EO_MATRIX_DIM == 17 + if (raidPtr->numCol > 17) { + printf("Number of stripe units in a parity stripe is bigger than 17. Please\n"); + printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n"); + printf("be 257 for encoding and decoding functions to work. \n"); + return(EINVAL); + } +#endif + layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; + layoutPtr->numParityCol = 2; + layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk; + raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit; + + raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; + + return(0); +} + +int rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr) +{ + return(20); +} + +RF_HeadSepLimit_t rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr) +{ + return(10); +} + +void rf_IdentifyStripeEvenOdd( + RF_Raid_t *raidPtr, + RF_RaidAddr_t addr, + RF_RowCol_t **diskids, + RF_RowCol_t *outRow) +{ + RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr); + RF_EvenOddConfigInfo_t *info = (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; + + *outRow = 0; + *diskids = info->stripeIdentifier[ stripeID % raidPtr->numCol ]; +} + +/* The layout of stripe unit on the disks are: c0 c1 c2 c3 c4 + + 0 1 2 E P + 5 E P 3 4 + P 6 7 8 E + 10 11 E P 9 + E P 12 13 14 + .... + + We use the MapSectorRAID5 to map data information because the routine can be shown to map exactly + the layout of data stripe unit as shown above although we have 2 redundant information now. + But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are different method from raid-5. +*/ + + +void rf_MapParityEvenOdd( + RF_Raid_t *raidPtr, + RF_RaidAddr_t raidSector, + RF_RowCol_t *row, + RF_RowCol_t *col, + RF_SectorNum_t *diskSector, + int remap) +{ + RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; + RF_StripeNum_t endSUIDofthisStrip = (SUID/raidPtr->Layout.numDataCol + 1)*raidPtr->Layout.numDataCol - 1; + + *row = 0; + *col = ( endSUIDofthisStrip + 2)%raidPtr->numCol; + *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + + (raidSector % raidPtr->Layout.sectorsPerStripeUnit); +} + +void rf_MapEEvenOdd( + RF_Raid_t *raidPtr, + RF_RaidAddr_t raidSector, + RF_RowCol_t *row, + RF_RowCol_t *col, + RF_SectorNum_t *diskSector, + int remap) +{ + RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; + RF_StripeNum_t endSUIDofthisStrip = (SUID/raidPtr->Layout.numDataCol + 1)*raidPtr->Layout.numDataCol - 1; + + *row = 0; + *col = ( endSUIDofthisStrip + 1)%raidPtr->numCol; + *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + + (raidSector % raidPtr->Layout.sectorsPerStripeUnit); +} + +void rf_EODagSelect( + RF_Raid_t *raidPtr, + RF_IoType_t type, + RF_AccessStripeMap_t *asmap, + RF_VoidFuncPtr *createFunc) +{ + RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); + unsigned ndfail = asmap->numDataFailed; + unsigned npfail = asmap->numParityFailed +asmap->numQFailed; + unsigned ntfail = npfail + ndfail; + + RF_ASSERT(RF_IO_IS_R_OR_W(type)); + if (ntfail > 2) + { + RF_ERRORMSG("more than two disks failed in a single group! Aborting I/O operation.\n"); + /* *infoFunc = */ *createFunc = NULL; + return; + } + + /* ok, we can do this I/O */ + if (type == RF_IO_TYPE_READ) + { + switch (ndfail) + { + case 0: + /* fault free read */ + *createFunc = (RF_VoidFuncPtr)rf_CreateFaultFreeReadDAG; /* same as raid 5 */ + break; + case 1: + /* lost a single data unit */ + /* two cases: + (1) parity is not lost. + do a normal raid 5 reconstruct read. + (2) parity is lost. + do a reconstruct read using "e". + */ + if (ntfail == 2) /* also lost redundancy */ + { + if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) + *createFunc = (RF_VoidFuncPtr)rf_EO_110_CreateReadDAG; + else + *createFunc = (RF_VoidFuncPtr)rf_EO_101_CreateReadDAG; + } + else + { + /* P and E are ok. But is there a failure + in some unaccessed data unit? + */ + if (rf_NumFailedDataUnitsInStripe(raidPtr,asmap)==2) + *createFunc = (RF_VoidFuncPtr)rf_EO_200_CreateReadDAG; + else + *createFunc = (RF_VoidFuncPtr)rf_EO_100_CreateReadDAG; + } + break; + case 2: + /* *createFunc = rf_EO_200_CreateReadDAG; */ + *createFunc = NULL; + break; + } + return; + } + + /* a write */ + switch (ntfail) + { + case 0: /* fault free */ + if (rf_suppressLocksAndLargeWrites || + (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) && (layoutPtr->numDataCol != 1)) || + (asmap->parityInfo->next != NULL) || (asmap->qInfo->next != NULL) || rf_CheckStripeForFailures(raidPtr, asmap))) { + + *createFunc = (RF_VoidFuncPtr)rf_EOCreateSmallWriteDAG; + } + else { + *createFunc = (RF_VoidFuncPtr)rf_EOCreateLargeWriteDAG; + } + break; + + case 1: /* single disk fault */ + if (npfail==1) + { + RF_ASSERT ((asmap->failedPDAs[0]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q)); + if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) + { /* q died, treat like normal mode raid5 write.*/ + if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1)) + || (asmap->parityInfo->next!=NULL) || rf_NumFailedDataUnitsInStripe(raidPtr,asmap)) + *createFunc = (RF_VoidFuncPtr)rf_EO_001_CreateSmallWriteDAG; + else + *createFunc = (RF_VoidFuncPtr)rf_EO_001_CreateLargeWriteDAG; + } + else + { /* parity died, small write only updating Q */ + if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1)) + || (asmap->qInfo->next!=NULL) || rf_NumFailedDataUnitsInStripe(raidPtr,asmap)) + *createFunc = (RF_VoidFuncPtr)rf_EO_010_CreateSmallWriteDAG; + else + *createFunc = (RF_VoidFuncPtr)rf_EO_010_CreateLargeWriteDAG; + } + } + else + { /* data missing. + Do a P reconstruct write if only a single data unit + is lost in the stripe, otherwise a reconstruct + write which employnig both P and E units. */ + if (rf_NumFailedDataUnitsInStripe(raidPtr,asmap)==2) + { + if (asmap->numStripeUnitsAccessed == 1) + *createFunc = (RF_VoidFuncPtr)rf_EO_200_CreateWriteDAG; + else + *createFunc = NULL; /* No direct support for this case now, like that in Raid-5 */ + } + else + { + if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit) + *createFunc = NULL; /* No direct support for this case now, like that in Raid-5 */ + else *createFunc = (RF_VoidFuncPtr)rf_EO_100_CreateWriteDAG; + } + } + break; + + case 2: /* two disk faults */ + switch (npfail) + { + case 2: /* both p and q dead */ + *createFunc = (RF_VoidFuncPtr)rf_EO_011_CreateWriteDAG; + break; + case 1: /* either p or q and dead data */ + RF_ASSERT(asmap->failedPDAs[0]->type == RF_PDA_TYPE_DATA); + RF_ASSERT ((asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q)); + if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) + { + if(asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit) + *createFunc = NULL; /* In both PQ and EvenOdd, no direct support for this case now, like that in Raid-5 */ + else + *createFunc = (RF_VoidFuncPtr)rf_EO_101_CreateWriteDAG; + } + else + { + if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit) + *createFunc = NULL; /* No direct support for this case, like that in Raid-5 */ + else + *createFunc = (RF_VoidFuncPtr)rf_EO_110_CreateWriteDAG; + } + break; + case 0: /* double data loss */ + /* if(asmap->failedPDAs[0]->numSector + asmap->failedPDAs[1]->numSector == 2 * layoutPtr->sectorsPerStripeUnit ) + *createFunc = rf_EOCreateLargeWriteDAG; + else */ + *createFunc = NULL; /* currently, in Evenodd, No support for simultaneous access of both failed SUs */ + break; + } + break; + + default: /* more than 2 disk faults */ + *createFunc = NULL; + RF_PANIC(); + } + return; +} + + +int rf_VerifyParityEvenOdd(raidPtr, raidAddr, parityPDA, correct_it, flags) + RF_Raid_t *raidPtr; + RF_RaidAddr_t raidAddr; + RF_PhysDiskAddr_t *parityPDA; + int correct_it; + RF_RaidAccessFlags_t flags; +{ + RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout); + RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr); + RF_SectorCount_t numsector = parityPDA->numSector; + int numbytes = rf_RaidAddressToByte(raidPtr, numsector); + int bytesPerStripe = numbytes * layoutPtr->numDataCol; + RF_DagHeader_t *rd_dag_h, *wr_dag_h; /* read, write dag */ + RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock; + RF_AccessStripeMapHeader_t *asm_h; + RF_AccessStripeMap_t *asmap; + RF_AllocListElem_t *alloclist; + RF_PhysDiskAddr_t *pda; + char *pbuf, *buf, *end_p, *p; + char *redundantbuf2; + int redundantTwoErr = 0, redundantOneErr = 0; + int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE, parity_corrected = RF_FALSE, red2_corrected = RF_FALSE; + int i, retcode; + RF_ReconUnitNum_t which_ru; + RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru); + int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol; + RF_AccTraceEntry_t tracerec; + RF_MCPair_t *mcpair; + + retcode = RF_PARITY_OKAY; + + mcpair = rf_AllocMCPair(); + rf_MakeAllocList(alloclist); + RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol), (char *), alloclist); + RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist); /* use calloc to make sure buffer is zeroed */ + end_p = buf + bytesPerStripe; + RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist); /* use calloc to make sure buffer is zeroed */ + + rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc, + "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY); + blockNode = rd_dag_h->succedents[0]; + unblockNode = blockNode->succedents[0]->succedents[0]; + + /* map the stripe and fill in the PDAs in the dag */ + asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP); + asmap = asm_h->stripeMap; + + for (pda=asmap->physInfo,i=0; i<layoutPtr->numDataCol; i++,pda=pda->next) { + RF_ASSERT(pda); + rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1); + RF_ASSERT(pda->numSector != 0); + if (rf_TryToRedirectPDA(raidPtr, pda, 0)) goto out; /* no way to verify parity if disk is dead. return w/ good status */ + blockNode->succedents[i]->params[0].p = pda; + blockNode->succedents[i]->params[2].v = psID; + blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru); + } + + RF_ASSERT(!asmap->parityInfo->next); + rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1); + RF_ASSERT(asmap->parityInfo->numSector != 0); + if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1)) + goto out; + blockNode->succedents[ layoutPtr->numDataCol ]->params[0].p = asmap->parityInfo; + + RF_ASSERT(!asmap->qInfo->next); + rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1); + RF_ASSERT(asmap->qInfo->numSector != 0); + if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1)) goto out; + /* + * if disk is dead, b/c no reconstruction is implemented right now, + * the function "rf_TryToRedirectPDA" always return one, which cause + * go to out and return w/ good status + */ + blockNode->succedents[ layoutPtr->numDataCol +1 ]->params[0].p = asmap->qInfo; + + /* fire off the DAG */ + bzero((char *)&tracerec,sizeof(tracerec)); + rd_dag_h->tracerec = &tracerec; + + if (rf_verifyParityDebug) { + printf("Parity verify read dag:\n"); + rf_PrintDAGList(rd_dag_h); + } + + RF_LOCK_MUTEX(mcpair->mutex); + mcpair->flag = 0; + rf_DispatchDAG(rd_dag_h, (void (*)(void *))rf_MCPairWakeupFunc, + (void *) mcpair); + while (!mcpair->flag) RF_WAIT_COND(mcpair->cond, mcpair->mutex); + RF_UNLOCK_MUTEX(mcpair->mutex); + if (rd_dag_h->status != rf_enable) { + RF_ERRORMSG("Unable to verify parity: can't read the stripe\n"); + retcode = RF_PARITY_COULD_NOT_VERIFY; + goto out; + } + + for (p=buf, i=0; p<end_p; p+=numbytes, i++) { + rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector); + /* + * the corresponding columes in EvenOdd encoding Matrix for these p pointers which point + * to the databuffer in a full stripe are sequentially from 0 to layoutPtr->numDataCol-1 + */ + rf_bxor(p, pbuf, numbytes, NULL); + } + RF_ASSERT(i==layoutPtr->numDataCol); + + for (i=0; i<numbytes; i++) { + if (pbuf[i] != buf[bytesPerStripe+i]) { + if (!correct_it) { + RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n", + i,(u_char) buf[bytesPerStripe+i],(u_char) pbuf[i]); + } + } + redundantOneErr = 1; + break; + } + + for (i=0; i<numbytes; i++) { + if (redundantbuf2[i] != buf[bytesPerStripe+numbytes+i]) { + if (!correct_it) { + RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n", + i,(u_char) buf[bytesPerStripe+numbytes+i],(u_char) redundantbuf2[i]); + } + redundantTwoErr = 1; + break; + } + } + if (redundantOneErr || redundantTwoErr ) + retcode = RF_PARITY_BAD; + + /* correct the first redundant disk, ie parity if it is error */ + if (redundantOneErr && correct_it) { + wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc, + "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY); + wrBlock = wr_dag_h->succedents[0]; wrUnblock = wrBlock->succedents[0]->succedents[0]; + wrBlock->succedents[0]->params[0].p = asmap->parityInfo; + wrBlock->succedents[0]->params[2].v = psID; + wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru); + bzero((char *)&tracerec,sizeof(tracerec)); + wr_dag_h->tracerec = &tracerec; + if (rf_verifyParityDebug) { + printf("Parity verify write dag:\n"); + rf_PrintDAGList(wr_dag_h); + } + RF_LOCK_MUTEX(mcpair->mutex); + mcpair->flag = 0; + rf_DispatchDAG(wr_dag_h, (void (*)(void *))rf_MCPairWakeupFunc, + (void *) mcpair); + while (!mcpair->flag) + RF_WAIT_COND(mcpair->cond, mcpair->mutex); + RF_UNLOCK_MUTEX(mcpair->mutex); + if (wr_dag_h->status != rf_enable) { + RF_ERRORMSG("Unable to correct parity in VerifyParity: can't write the stripe\n"); + parity_cant_correct = RF_TRUE; + } else { + parity_corrected = RF_TRUE; + } + rf_FreeDAG(wr_dag_h); + } + + if (redundantTwoErr && correct_it) { + wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc, + "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY); + wrBlock = wr_dag_h->succedents[0]; wrUnblock = wrBlock->succedents[0]->succedents[0]; + wrBlock->succedents[0]->params[0].p = asmap->qInfo; + wrBlock->succedents[0]->params[2].v = psID; + wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru); + bzero((char *)&tracerec,sizeof(tracerec)); + wr_dag_h->tracerec = &tracerec; + if (rf_verifyParityDebug) { + printf("Dag of write new second redundant information in parity verify :\n"); + rf_PrintDAGList(wr_dag_h); + } + RF_LOCK_MUTEX(mcpair->mutex); + mcpair->flag = 0; + rf_DispatchDAG(wr_dag_h, (void (*)(void *))rf_MCPairWakeupFunc, + (void *) mcpair); + while (!mcpair->flag) + RF_WAIT_COND(mcpair->cond, mcpair->mutex); + RF_UNLOCK_MUTEX(mcpair->mutex); + if (wr_dag_h->status != rf_enable) { + RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n"); + red2_cant_correct = RF_TRUE; + } else { + red2_corrected = RF_TRUE; + } + rf_FreeDAG(wr_dag_h); + } + if ( (redundantOneErr && parity_cant_correct) || + (redundantTwoErr && red2_cant_correct )) + retcode = RF_PARITY_COULD_NOT_CORRECT; + if ( (retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected ) + retcode = RF_PARITY_CORRECTED; + + +out: + rf_FreeAccessStripeMap(asm_h); + rf_FreeAllocList(alloclist); + rf_FreeDAG(rd_dag_h); + rf_FreeMCPair(mcpair); + return(retcode); +} + +#endif /* RF_INCLUDE_EVENODD > 0 */ |