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