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