Home | History | Annotate | Line # | Download | only in raidframe
rf_evenodd.c revision 1.2
      1 /*	$NetBSD: rf_evenodd.c,v 1.2 1999/02/05 00:06:11 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_sys.h"
     59 #include "rf_evenodd.h"
     60 #include "rf_evenodd_dagfuncs.h"
     61 #include "rf_evenodd_dags.h"
     62 #include "rf_engine.h"
     63 
     64 typedef struct RF_EvenOddConfigInfo_s {
     65 	RF_RowCol_t **stripeIdentifier;	/* filled in at config time & used by
     66 					 * IdentifyStripe */
     67 }       RF_EvenOddConfigInfo_t;
     68 
     69 int
     70 rf_ConfigureEvenOdd(listp, raidPtr, cfgPtr)
     71 	RF_ShutdownList_t **listp;
     72 	RF_Raid_t *raidPtr;
     73 	RF_Config_t *cfgPtr;
     74 {
     75 	RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
     76 	RF_EvenOddConfigInfo_t *info;
     77 	RF_RowCol_t i, j, startdisk;
     78 
     79 	RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
     80 	layoutPtr->layoutSpecificInfo = (void *) info;
     81 
     82 	RF_ASSERT(raidPtr->numRow == 1);
     83 
     84 	info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList);
     85 	startdisk = 0;
     86 	for (i = 0; i < raidPtr->numCol; i++) {
     87 		for (j = 0; j < raidPtr->numCol; j++) {
     88 			info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol;
     89 		}
     90 		if ((startdisk -= 2) < 0)
     91 			startdisk += raidPtr->numCol;
     92 	}
     93 
     94 	/* fill in the remaining layout parameters */
     95 	layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
     96 	layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector;
     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 		 /* *infoFunc = */ *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_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);	/* use calloc to make
    388 									 * sure buffer is zeroed */
    389 	end_p = buf + bytesPerStripe;
    390 	RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);	/* use calloc to make
    391 										 * sure buffer is zeroed */
    392 
    393 	rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc,
    394 	    "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    395 	blockNode = rd_dag_h->succedents[0];
    396 	unblockNode = blockNode->succedents[0]->succedents[0];
    397 
    398 	/* map the stripe and fill in the PDAs in the dag */
    399 	asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
    400 	asmap = asm_h->stripeMap;
    401 
    402 	for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol; i++, pda = pda->next) {
    403 		RF_ASSERT(pda);
    404 		rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
    405 		RF_ASSERT(pda->numSector != 0);
    406 		if (rf_TryToRedirectPDA(raidPtr, pda, 0))
    407 			goto out;	/* no way to verify parity if disk is
    408 					 * dead.  return w/ good status */
    409 		blockNode->succedents[i]->params[0].p = pda;
    410 		blockNode->succedents[i]->params[2].v = psID;
    411 		blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    412 	}
    413 
    414 	RF_ASSERT(!asmap->parityInfo->next);
    415 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
    416 	RF_ASSERT(asmap->parityInfo->numSector != 0);
    417 	if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
    418 		goto out;
    419 	blockNode->succedents[layoutPtr->numDataCol]->params[0].p = asmap->parityInfo;
    420 
    421 	RF_ASSERT(!asmap->qInfo->next);
    422 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
    423 	RF_ASSERT(asmap->qInfo->numSector != 0);
    424 	if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
    425 		goto out;
    426 	/* if disk is dead, b/c no reconstruction is implemented right now,
    427 	 * the function "rf_TryToRedirectPDA" always return one, which cause
    428 	 * go to out and return w/ good status   */
    429 	blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p = asmap->qInfo;
    430 
    431 	/* fire off the DAG */
    432 	bzero((char *) &tracerec, sizeof(tracerec));
    433 	rd_dag_h->tracerec = &tracerec;
    434 
    435 	if (rf_verifyParityDebug) {
    436 		printf("Parity verify read dag:\n");
    437 		rf_PrintDAGList(rd_dag_h);
    438 	}
    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 		bzero((char *) &tracerec, sizeof(tracerec));
    494 		wr_dag_h->tracerec = &tracerec;
    495 		if (rf_verifyParityDebug) {
    496 			printf("Parity verify write dag:\n");
    497 			rf_PrintDAGList(wr_dag_h);
    498 		}
    499 		RF_LOCK_MUTEX(mcpair->mutex);
    500 		mcpair->flag = 0;
    501 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    502 		    (void *) mcpair);
    503 		while (!mcpair->flag)
    504 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    505 		RF_UNLOCK_MUTEX(mcpair->mutex);
    506 		if (wr_dag_h->status != rf_enable) {
    507 			RF_ERRORMSG("Unable to correct parity in VerifyParity:  can't write the stripe\n");
    508 			parity_cant_correct = RF_TRUE;
    509 		} else {
    510 			parity_corrected = RF_TRUE;
    511 		}
    512 		rf_FreeDAG(wr_dag_h);
    513 	}
    514 	if (redundantTwoErr && correct_it) {
    515 		wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
    516 		    "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    517 		wrBlock = wr_dag_h->succedents[0];
    518 		wrUnblock = wrBlock->succedents[0]->succedents[0];
    519 		wrBlock->succedents[0]->params[0].p = asmap->qInfo;
    520 		wrBlock->succedents[0]->params[2].v = psID;
    521 		wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    522 		bzero((char *) &tracerec, sizeof(tracerec));
    523 		wr_dag_h->tracerec = &tracerec;
    524 		if (rf_verifyParityDebug) {
    525 			printf("Dag of write new second redundant information in parity verify :\n");
    526 			rf_PrintDAGList(wr_dag_h);
    527 		}
    528 		RF_LOCK_MUTEX(mcpair->mutex);
    529 		mcpair->flag = 0;
    530 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    531 		    (void *) mcpair);
    532 		while (!mcpair->flag)
    533 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    534 		RF_UNLOCK_MUTEX(mcpair->mutex);
    535 		if (wr_dag_h->status != rf_enable) {
    536 			RF_ERRORMSG("Unable to correct second redundant information in VerifyParity:  can't write the stripe\n");
    537 			red2_cant_correct = RF_TRUE;
    538 		} else {
    539 			red2_corrected = RF_TRUE;
    540 		}
    541 		rf_FreeDAG(wr_dag_h);
    542 	}
    543 	if ((redundantOneErr && parity_cant_correct) ||
    544 	    (redundantTwoErr && red2_cant_correct))
    545 		retcode = RF_PARITY_COULD_NOT_CORRECT;
    546 	if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
    547 		retcode = RF_PARITY_CORRECTED;
    548 
    549 
    550 out:
    551 	rf_FreeAccessStripeMap(asm_h);
    552 	rf_FreeAllocList(alloclist);
    553 	rf_FreeDAG(rd_dag_h);
    554 	rf_FreeMCPair(mcpair);
    555 	return (retcode);
    556 }
    557 #endif				/* RF_INCLUDE_EVENODD > 0 */
    558