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