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