Home | History | Annotate | Line # | Download | only in raidframe
rf_evenodd.c revision 1.3
      1 /*	$NetBSD: rf_evenodd.c,v 1.3 1999/08/13 03:41:56 oster Exp $	*/
      2 /*
      3  * Copyright (c) 1995 Carnegie-Mellon University.
      4  * All rights reserved.
      5  *
      6  * Author: Chang-Ming Wu
      7  *
      8  * Permission to use, copy, modify and distribute this software and
      9  * its documentation is hereby granted, provided that both the copyright
     10  * notice and this permission notice appear in all copies of the
     11  * software, derivative works or modified versions, and any portions
     12  * thereof, and that both notices appear in supporting documentation.
     13  *
     14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  *
     18  * Carnegie Mellon requests users of this software to return to
     19  *
     20  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  *  School of Computer Science
     22  *  Carnegie Mellon University
     23  *  Pittsburgh PA 15213-3890
     24  *
     25  * any improvements or extensions that they make and grant Carnegie the
     26  * rights to redistribute these changes.
     27  */
     28 
     29 /*****************************************************************************************
     30  *
     31  * rf_evenodd.c -- implements EVENODD array architecture
     32  *
     33  ****************************************************************************************/
     34 
     35 #include "rf_archs.h"
     36 
     37 #if RF_INCLUDE_EVENODD > 0
     38 
     39 #include "rf_types.h"
     40 #include "rf_raid.h"
     41 #include "rf_dag.h"
     42 #include "rf_dagffrd.h"
     43 #include "rf_dagffwr.h"
     44 #include "rf_dagdegrd.h"
     45 #include "rf_dagdegwr.h"
     46 #include "rf_dagutils.h"
     47 #include "rf_dagfuncs.h"
     48 #include "rf_threadid.h"
     49 #include "rf_etimer.h"
     50 #include "rf_general.h"
     51 #include "rf_evenodd.h"
     52 #include "rf_configure.h"
     53 #include "rf_parityscan.h"
     54 #include "rf_utils.h"
     55 #include "rf_map.h"
     56 #include "rf_pq.h"
     57 #include "rf_mcpair.h"
     58 #include "rf_evenodd.h"
     59 #include "rf_evenodd_dagfuncs.h"
     60 #include "rf_evenodd_dags.h"
     61 #include "rf_engine.h"
     62 
     63 typedef struct RF_EvenOddConfigInfo_s {
     64 	RF_RowCol_t **stripeIdentifier;	/* filled in at config time & used by
     65 					 * IdentifyStripe */
     66 }       RF_EvenOddConfigInfo_t;
     67 
     68 int
     69 rf_ConfigureEvenOdd(listp, raidPtr, cfgPtr)
     70 	RF_ShutdownList_t **listp;
     71 	RF_Raid_t *raidPtr;
     72 	RF_Config_t *cfgPtr;
     73 {
     74 	RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
     75 	RF_EvenOddConfigInfo_t *info;
     76 	RF_RowCol_t i, j, startdisk;
     77 
     78 	RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
     79 	layoutPtr->layoutSpecificInfo = (void *) info;
     80 
     81 	RF_ASSERT(raidPtr->numRow == 1);
     82 
     83 	info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList);
     84 	startdisk = 0;
     85 	for (i = 0; i < raidPtr->numCol; i++) {
     86 		for (j = 0; j < raidPtr->numCol; j++) {
     87 			info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol;
     88 		}
     89 		if ((startdisk -= 2) < 0)
     90 			startdisk += raidPtr->numCol;
     91 	}
     92 
     93 	/* fill in the remaining layout parameters */
     94 	layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
     95 	layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector;
     96 	layoutPtr->numDataCol = raidPtr->numCol - 2;	/* ORIG:
     97 							 * layoutPtr->numDataCol
     98 							 * = raidPtr->numCol-1;  */
     99 #if RF_EO_MATRIX_DIM > 17
    100 	if (raidPtr->numCol <= 17) {
    101 		printf("Number of stripe units in a parity stripe is smaller than 17. Please\n");
    102 		printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
    103 		printf("be 17 to increase performance. \n");
    104 		return (EINVAL);
    105 	}
    106 #elif RF_EO_MATRIX_DIM == 17
    107 	if (raidPtr->numCol > 17) {
    108 		printf("Number of stripe units in a parity stripe is bigger than 17. Please\n");
    109 		printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
    110 		printf("be 257 for encoding and decoding functions to work. \n");
    111 		return (EINVAL);
    112 	}
    113 #endif
    114 	layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    115 	layoutPtr->numParityCol = 2;
    116 	layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
    117 	raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    118 
    119 	raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    120 
    121 	return (0);
    122 }
    123 
    124 int
    125 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t * raidPtr)
    126 {
    127 	return (20);
    128 }
    129 
    130 RF_HeadSepLimit_t
    131 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t * raidPtr)
    132 {
    133 	return (10);
    134 }
    135 
    136 void
    137 rf_IdentifyStripeEvenOdd(
    138     RF_Raid_t * raidPtr,
    139     RF_RaidAddr_t addr,
    140     RF_RowCol_t ** diskids,
    141     RF_RowCol_t * outRow)
    142 {
    143 	RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
    144 	RF_EvenOddConfigInfo_t *info = (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    145 
    146 	*outRow = 0;
    147 	*diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
    148 }
    149 /* The layout of stripe unit on the disks are:      c0 c1 c2 c3 c4
    150 
    151  						     0  1  2  E  P
    152 						     5  E  P  3  4
    153 						     P  6  7  8  E
    154 	 					    10 11  E  P  9
    155 						     E  P 12 13 14
    156 						     ....
    157 
    158   We use the MapSectorRAID5 to map data information because the routine can be shown to map exactly
    159   the layout of data stripe unit as shown above although we have 2 redundant information now.
    160   But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are different method from raid-5.
    161 */
    162 
    163 
    164 void
    165 rf_MapParityEvenOdd(
    166     RF_Raid_t * raidPtr,
    167     RF_RaidAddr_t raidSector,
    168     RF_RowCol_t * row,
    169     RF_RowCol_t * col,
    170     RF_SectorNum_t * diskSector,
    171     int remap)
    172 {
    173 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    174 	RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
    175 
    176 	*row = 0;
    177 	*col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
    178 	*diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
    179 	    (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    180 }
    181 
    182 void
    183 rf_MapEEvenOdd(
    184     RF_Raid_t * raidPtr,
    185     RF_RaidAddr_t raidSector,
    186     RF_RowCol_t * row,
    187     RF_RowCol_t * col,
    188     RF_SectorNum_t * diskSector,
    189     int remap)
    190 {
    191 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    192 	RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
    193 
    194 	*row = 0;
    195 	*col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
    196 	*diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
    197 	    (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    198 }
    199 
    200 void
    201 rf_EODagSelect(
    202     RF_Raid_t * raidPtr,
    203     RF_IoType_t type,
    204     RF_AccessStripeMap_t * asmap,
    205     RF_VoidFuncPtr * createFunc)
    206 {
    207 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    208 	unsigned ndfail = asmap->numDataFailed;
    209 	unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
    210 	unsigned ntfail = npfail + ndfail;
    211 
    212 	RF_ASSERT(RF_IO_IS_R_OR_W(type));
    213 	if (ntfail > 2) {
    214 		RF_ERRORMSG("more than two disks failed in a single group!  Aborting I/O operation.\n");
    215 		 /* *infoFunc = */ *createFunc = NULL;
    216 		return;
    217 	}
    218 	/* ok, we can do this I/O */
    219 	if (type == RF_IO_TYPE_READ) {
    220 		switch (ndfail) {
    221 		case 0:
    222 			/* fault free read */
    223 			*createFunc = (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG;	/* same as raid 5 */
    224 			break;
    225 		case 1:
    226 			/* lost a single data unit */
    227 			/* two cases: (1) parity is not lost. do a normal raid
    228 			 * 5 reconstruct read. (2) parity is lost. do a
    229 			 * reconstruct read using "e". */
    230 			if (ntfail == 2) {	/* also lost redundancy */
    231 				if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY)
    232 					*createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateReadDAG;
    233 				else
    234 					*createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateReadDAG;
    235 			} else {
    236 				/* P and E are ok. But is there a failure in
    237 				 * some unaccessed data unit? */
    238 				if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
    239 					*createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateReadDAG;
    240 				else
    241 					*createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateReadDAG;
    242 			}
    243 			break;
    244 		case 2:
    245 			/* *createFunc = rf_EO_200_CreateReadDAG; */
    246 			*createFunc = NULL;
    247 			break;
    248 		}
    249 		return;
    250 	}
    251 	/* a write */
    252 	switch (ntfail) {
    253 	case 0:		/* fault free */
    254 		if (rf_suppressLocksAndLargeWrites ||
    255 		    (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) && (layoutPtr->numDataCol != 1)) ||
    256 			(asmap->parityInfo->next != NULL) || (asmap->qInfo->next != NULL) || rf_CheckStripeForFailures(raidPtr, asmap))) {
    257 
    258 			*createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
    259 		} else {
    260 			*createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
    261 		}
    262 		break;
    263 
    264 	case 1:		/* single disk fault */
    265 		if (npfail == 1) {
    266 			RF_ASSERT((asmap->failedPDAs[0]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
    267 			if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {	/* q died, treat like
    268 										 * normal mode raid5
    269 										 * write. */
    270 				if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
    271 				    || (asmap->parityInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
    272 					*createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateSmallWriteDAG;
    273 				else
    274 					*createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateLargeWriteDAG;
    275 			} else {/* parity died, small write only updating Q */
    276 				if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
    277 				    || (asmap->qInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
    278 					*createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateSmallWriteDAG;
    279 				else
    280 					*createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateLargeWriteDAG;
    281 			}
    282 		} else {	/* data missing. Do a P reconstruct write if
    283 				 * only a single data unit is lost in the
    284 				 * stripe, otherwise a reconstruct write which
    285 				 * employnig both P and E units. */
    286 			if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2) {
    287 				if (asmap->numStripeUnitsAccessed == 1)
    288 					*createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateWriteDAG;
    289 				else
    290 					*createFunc = NULL;	/* No direct support for
    291 								 * this case now, like
    292 								 * that in Raid-5  */
    293 			} else {
    294 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    295 					*createFunc = NULL;	/* No direct support for
    296 								 * this case now, like
    297 								 * that in Raid-5  */
    298 				else
    299 					*createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateWriteDAG;
    300 			}
    301 		}
    302 		break;
    303 
    304 	case 2:		/* two disk faults */
    305 		switch (npfail) {
    306 		case 2:	/* both p and q dead */
    307 			*createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
    308 			break;
    309 		case 1:	/* either p or q and dead data */
    310 			RF_ASSERT(asmap->failedPDAs[0]->type == RF_PDA_TYPE_DATA);
    311 			RF_ASSERT((asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
    312 			if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
    313 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    314 					*createFunc = NULL;	/* In both PQ and
    315 								 * EvenOdd, no direct
    316 								 * support for this case
    317 								 * now, like that in
    318 								 * Raid-5  */
    319 				else
    320 					*createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateWriteDAG;
    321 			} else {
    322 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    323 					*createFunc = NULL;	/* No direct support for
    324 								 * this case, like that
    325 								 * in Raid-5  */
    326 				else
    327 					*createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateWriteDAG;
    328 			}
    329 			break;
    330 		case 0:	/* double data loss */
    331 			/* if(asmap->failedPDAs[0]->numSector +
    332 			 * asmap->failedPDAs[1]->numSector == 2 *
    333 			 * layoutPtr->sectorsPerStripeUnit ) createFunc =
    334 			 * rf_EOCreateLargeWriteDAG; else    							 */
    335 			*createFunc = NULL;	/* currently, in Evenodd, No
    336 						 * support for simultaneous
    337 						 * access of both failed SUs */
    338 			break;
    339 		}
    340 		break;
    341 
    342 	default:		/* more than 2 disk faults */
    343 		*createFunc = NULL;
    344 		RF_PANIC();
    345 	}
    346 	return;
    347 }
    348 
    349 
    350 int
    351 rf_VerifyParityEvenOdd(raidPtr, raidAddr, parityPDA, correct_it, flags)
    352 	RF_Raid_t *raidPtr;
    353 	RF_RaidAddr_t raidAddr;
    354 	RF_PhysDiskAddr_t *parityPDA;
    355 	int     correct_it;
    356 	RF_RaidAccessFlags_t flags;
    357 {
    358 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    359 	RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
    360 	RF_SectorCount_t numsector = parityPDA->numSector;
    361 	int     numbytes = rf_RaidAddressToByte(raidPtr, numsector);
    362 	int     bytesPerStripe = numbytes * layoutPtr->numDataCol;
    363 	RF_DagHeader_t *rd_dag_h, *wr_dag_h;	/* read, write dag */
    364 	RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
    365 	RF_AccessStripeMapHeader_t *asm_h;
    366 	RF_AccessStripeMap_t *asmap;
    367 	RF_AllocListElem_t *alloclist;
    368 	RF_PhysDiskAddr_t *pda;
    369 	char   *pbuf, *buf, *end_p, *p;
    370 	char   *redundantbuf2;
    371 	int     redundantTwoErr = 0, redundantOneErr = 0;
    372 	int     parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
    373 	        parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
    374 	int     i, retcode;
    375 	RF_ReconUnitNum_t which_ru;
    376 	RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
    377 	int     stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
    378 	RF_AccTraceEntry_t tracerec;
    379 	RF_MCPair_t *mcpair;
    380 
    381 	retcode = RF_PARITY_OKAY;
    382 
    383 	mcpair = rf_AllocMCPair();
    384 	rf_MakeAllocList(alloclist);
    385 	RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol), (char *), alloclist);
    386 	RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);	/* use calloc to make
    387 									 * sure buffer is zeroed */
    388 	end_p = buf + bytesPerStripe;
    389 	RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);	/* use calloc to make
    390 										 * sure buffer is zeroed */
    391 
    392 	rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc,
    393 	    "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    394 	blockNode = rd_dag_h->succedents[0];
    395 	unblockNode = blockNode->succedents[0]->succedents[0];
    396 
    397 	/* map the stripe and fill in the PDAs in the dag */
    398 	asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
    399 	asmap = asm_h->stripeMap;
    400 
    401 	for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol; i++, pda = pda->next) {
    402 		RF_ASSERT(pda);
    403 		rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
    404 		RF_ASSERT(pda->numSector != 0);
    405 		if (rf_TryToRedirectPDA(raidPtr, pda, 0))
    406 			goto out;	/* no way to verify parity if disk is
    407 					 * dead.  return w/ good status */
    408 		blockNode->succedents[i]->params[0].p = pda;
    409 		blockNode->succedents[i]->params[2].v = psID;
    410 		blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    411 	}
    412 
    413 	RF_ASSERT(!asmap->parityInfo->next);
    414 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
    415 	RF_ASSERT(asmap->parityInfo->numSector != 0);
    416 	if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
    417 		goto out;
    418 	blockNode->succedents[layoutPtr->numDataCol]->params[0].p = asmap->parityInfo;
    419 
    420 	RF_ASSERT(!asmap->qInfo->next);
    421 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
    422 	RF_ASSERT(asmap->qInfo->numSector != 0);
    423 	if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
    424 		goto out;
    425 	/* if disk is dead, b/c no reconstruction is implemented right now,
    426 	 * the function "rf_TryToRedirectPDA" always return one, which cause
    427 	 * go to out and return w/ good status   */
    428 	blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p = asmap->qInfo;
    429 
    430 	/* fire off the DAG */
    431 	bzero((char *) &tracerec, sizeof(tracerec));
    432 	rd_dag_h->tracerec = &tracerec;
    433 
    434 	if (rf_verifyParityDebug) {
    435 		printf("Parity verify read dag:\n");
    436 		rf_PrintDAGList(rd_dag_h);
    437 	}
    438 	RF_LOCK_MUTEX(mcpair->mutex);
    439 	mcpair->flag = 0;
    440 	rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    441 	    (void *) mcpair);
    442 	while (!mcpair->flag)
    443 		RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    444 	RF_UNLOCK_MUTEX(mcpair->mutex);
    445 	if (rd_dag_h->status != rf_enable) {
    446 		RF_ERRORMSG("Unable to verify parity:  can't read the stripe\n");
    447 		retcode = RF_PARITY_COULD_NOT_VERIFY;
    448 		goto out;
    449 	}
    450 	for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
    451 		rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector);
    452 		/* the corresponding columes in EvenOdd encoding Matrix for
    453 		 * these p pointers which point to the databuffer in a full
    454 		 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */
    455 		rf_bxor(p, pbuf, numbytes, NULL);
    456 	}
    457 	RF_ASSERT(i == layoutPtr->numDataCol);
    458 
    459 	for (i = 0; i < numbytes; i++) {
    460 		if (pbuf[i] != buf[bytesPerStripe + i]) {
    461 			if (!correct_it) {
    462 				RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n",
    463 				    i, (u_char) buf[bytesPerStripe + i], (u_char) pbuf[i]);
    464 			}
    465 		}
    466 		redundantOneErr = 1;
    467 		break;
    468 	}
    469 
    470 	for (i = 0; i < numbytes; i++) {
    471 		if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
    472 			if (!correct_it) {
    473 				RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n",
    474 				    i, (u_char) buf[bytesPerStripe + numbytes + i], (u_char) redundantbuf2[i]);
    475 			}
    476 			redundantTwoErr = 1;
    477 			break;
    478 		}
    479 	}
    480 	if (redundantOneErr || redundantTwoErr)
    481 		retcode = RF_PARITY_BAD;
    482 
    483 	/* correct the first redundant disk, ie parity if it is error    */
    484 	if (redundantOneErr && correct_it) {
    485 		wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
    486 		    "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    487 		wrBlock = wr_dag_h->succedents[0];
    488 		wrUnblock = wrBlock->succedents[0]->succedents[0];
    489 		wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
    490 		wrBlock->succedents[0]->params[2].v = psID;
    491 		wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    492 		bzero((char *) &tracerec, sizeof(tracerec));
    493 		wr_dag_h->tracerec = &tracerec;
    494 		if (rf_verifyParityDebug) {
    495 			printf("Parity verify write dag:\n");
    496 			rf_PrintDAGList(wr_dag_h);
    497 		}
    498 		RF_LOCK_MUTEX(mcpair->mutex);
    499 		mcpair->flag = 0;
    500 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    501 		    (void *) mcpair);
    502 		while (!mcpair->flag)
    503 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    504 		RF_UNLOCK_MUTEX(mcpair->mutex);
    505 		if (wr_dag_h->status != rf_enable) {
    506 			RF_ERRORMSG("Unable to correct parity in VerifyParity:  can't write the stripe\n");
    507 			parity_cant_correct = RF_TRUE;
    508 		} else {
    509 			parity_corrected = RF_TRUE;
    510 		}
    511 		rf_FreeDAG(wr_dag_h);
    512 	}
    513 	if (redundantTwoErr && correct_it) {
    514 		wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
    515 		    "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    516 		wrBlock = wr_dag_h->succedents[0];
    517 		wrUnblock = wrBlock->succedents[0]->succedents[0];
    518 		wrBlock->succedents[0]->params[0].p = asmap->qInfo;
    519 		wrBlock->succedents[0]->params[2].v = psID;
    520 		wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    521 		bzero((char *) &tracerec, sizeof(tracerec));
    522 		wr_dag_h->tracerec = &tracerec;
    523 		if (rf_verifyParityDebug) {
    524 			printf("Dag of write new second redundant information in parity verify :\n");
    525 			rf_PrintDAGList(wr_dag_h);
    526 		}
    527 		RF_LOCK_MUTEX(mcpair->mutex);
    528 		mcpair->flag = 0;
    529 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    530 		    (void *) mcpair);
    531 		while (!mcpair->flag)
    532 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    533 		RF_UNLOCK_MUTEX(mcpair->mutex);
    534 		if (wr_dag_h->status != rf_enable) {
    535 			RF_ERRORMSG("Unable to correct second redundant information in VerifyParity:  can't write the stripe\n");
    536 			red2_cant_correct = RF_TRUE;
    537 		} else {
    538 			red2_corrected = RF_TRUE;
    539 		}
    540 		rf_FreeDAG(wr_dag_h);
    541 	}
    542 	if ((redundantOneErr && parity_cant_correct) ||
    543 	    (redundantTwoErr && red2_cant_correct))
    544 		retcode = RF_PARITY_COULD_NOT_CORRECT;
    545 	if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
    546 		retcode = RF_PARITY_CORRECTED;
    547 
    548 
    549 out:
    550 	rf_FreeAccessStripeMap(asm_h);
    551 	rf_FreeAllocList(alloclist);
    552 	rf_FreeDAG(rd_dag_h);
    553 	rf_FreeMCPair(mcpair);
    554 	return (retcode);
    555 }
    556 #endif				/* RF_INCLUDE_EVENODD > 0 */
    557