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