File: [local] / sys / dev / raidframe / rf_evenodd.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:09:47 2008 UTC (16 years, 4 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/* $OpenBSD: rf_evenodd.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $ */
/* $NetBSD: rf_evenodd.c,v 1.4 2000/01/07 03:40:59 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_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_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(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\ndefine the macro RF_EO_MATRIX_DIM in"
" file rf_evenodd_dagfuncs.h to\nbe 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\ndefine the macro RF_EO_MATRIX_DIM in"
" file rf_evenodd_dagfuncs.h to\nbe 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
* is employing both P and E units.
*/
if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
{
if (asmap->numStripeUnitsAccessed == 1)
*createFunc = (RF_VoidFuncPtr)
rf_EO_200_CreateWriteDAG;
else
/*
* No direct support for this case now,
* like that in Raid-5.
*/
*createFunc = NULL;
} else {
if (asmap->numStripeUnitsAccessed != 1 &&
asmap->failedPDAs[0]->numSector !=
layoutPtr->sectorsPerStripeUnit)
/*
* No direct support for this case now,
* like that in Raid-5.
*/
*createFunc = NULL;
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)
/*
* In both PQ and EvenOdd, no direct
* support for this case now, like that
* in Raid-5.
*/
*createFunc = NULL;
else
*createFunc = (RF_VoidFuncPtr)
rf_EO_101_CreateWriteDAG;
} else {
if (asmap->numStripeUnitsAccessed != 1 &&
asmap->failedPDAs[0]->numSector !=
layoutPtr->sectorsPerStripeUnit)
/*
* No direct support for this case,
* like that in Raid-5.
*/
*createFunc = NULL;
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(
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);
/* Use calloc to make sure buffer is zeroed. */
RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
end_p = buf + bytesPerStripe;
/* Use calloc to make sure buffer is zeroed. */
RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);
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))
/*
* No way to verify parity if disk is dead.
* Return w/ good status.
*/
goto out;
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 causes
* 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 columns in EvenOdd encoding Matrix for
* these p pointers that point to the databuffer in a full
* stripe are sequential 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 */