rf_evenodd.c revision 1.15.12.1 1 /* $NetBSD: rf_evenodd.c,v 1.15.12.1 2006/05/24 15:50:29 tron 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.15.12.1 2006/05/24 15:50:29 tron 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 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList);
82 startdisk = 0;
83 for (i = 0; i < raidPtr->numCol; i++) {
84 for (j = 0; j < raidPtr->numCol; j++) {
85 info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol;
86 }
87 if ((startdisk -= 2) < 0)
88 startdisk += raidPtr->numCol;
89 }
90
91 /* fill in the remaining layout parameters */
92 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
93 layoutPtr->numDataCol = raidPtr->numCol - 2; /* ORIG:
94 * layoutPtr->numDataCol
95 * = raidPtr->numCol-1; */
96 #if RF_EO_MATRIX_DIM > 17
97 if (raidPtr->numCol <= 17) {
98 printf("Number of stripe units in a parity stripe is smaller than 17. Please\n");
99 printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
100 printf("be 17 to increase performance. \n");
101 return (EINVAL);
102 }
103 #elif RF_EO_MATRIX_DIM == 17
104 if (raidPtr->numCol > 17) {
105 printf("Number of stripe units in a parity stripe is bigger than 17. Please\n");
106 printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
107 printf("be 257 for encoding and decoding functions to work. \n");
108 return (EINVAL);
109 }
110 #endif
111 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
112 layoutPtr->numParityCol = 2;
113 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
114 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
115
116 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
117
118 return (0);
119 }
120
121 int
122 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr)
123 {
124 return (20);
125 }
126
127 RF_HeadSepLimit_t
128 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr)
129 {
130 return (10);
131 }
132
133 void
134 rf_IdentifyStripeEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
135 RF_RowCol_t **diskids)
136 {
137 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
138 RF_EvenOddConfigInfo_t *info = (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
139
140 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
141 }
142 /* The layout of stripe unit on the disks are: c0 c1 c2 c3 c4
143
144 0 1 2 E P
145 5 E P 3 4
146 P 6 7 8 E
147 10 11 E P 9
148 E P 12 13 14
149 ....
150
151 We use the MapSectorRAID5 to map data information because the routine can be shown to map exactly
152 the layout of data stripe unit as shown above although we have 2 redundant information now.
153 But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are different method from raid-5.
154 */
155
156
157 void
158 rf_MapParityEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
159 RF_RowCol_t *col,
160 RF_SectorNum_t *diskSector, int remap)
161 {
162 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
163 RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
164
165 *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
166 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
167 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
168 }
169
170 void
171 rf_MapEEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
172 RF_RowCol_t *col, RF_SectorNum_t *diskSector,
173 int remap)
174 {
175 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
176 RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
177
178 *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
179 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
180 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
181 }
182
183 void
184 rf_EODagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
185 RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
186 {
187 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
188 unsigned ndfail = asmap->numDataFailed;
189 unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
190 unsigned ntfail = npfail + ndfail;
191
192 RF_ASSERT(RF_IO_IS_R_OR_W(type));
193 if (ntfail > 2) {
194 RF_ERRORMSG("more than two disks failed in a single group! Aborting I/O operation.\n");
195 *createFunc = NULL;
196 return;
197 }
198 /* ok, we can do this I/O */
199 if (type == RF_IO_TYPE_READ) {
200 switch (ndfail) {
201 case 0:
202 /* fault free read */
203 *createFunc = (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG; /* same as raid 5 */
204 break;
205 case 1:
206 /* lost a single data unit */
207 /* two cases: (1) parity is not lost. do a normal raid
208 * 5 reconstruct read. (2) parity is lost. do a
209 * reconstruct read using "e". */
210 if (ntfail == 2) { /* also lost redundancy */
211 if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY)
212 *createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateReadDAG;
213 else
214 *createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateReadDAG;
215 } else {
216 /* P and E are ok. But is there a failure in
217 * some unaccessed data unit? */
218 if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
219 *createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateReadDAG;
220 else
221 *createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateReadDAG;
222 }
223 break;
224 case 2:
225 /* *createFunc = rf_EO_200_CreateReadDAG; */
226 *createFunc = NULL;
227 break;
228 }
229 return;
230 }
231 /* a write */
232 switch (ntfail) {
233 case 0: /* fault free */
234 if (rf_suppressLocksAndLargeWrites ||
235 (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) && (layoutPtr->numDataCol != 1)) ||
236 (asmap->parityInfo->next != NULL) || (asmap->qInfo->next != NULL) || rf_CheckStripeForFailures(raidPtr, asmap))) {
237
238 *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
239 } else {
240 *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
241 }
242 break;
243
244 case 1: /* single disk fault */
245 if (npfail == 1) {
246 RF_ASSERT((asmap->failedPDAs[0]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
247 if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) { /* q died, treat like
248 * normal mode raid5
249 * write. */
250 if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
251 || (asmap->parityInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
252 *createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateSmallWriteDAG;
253 else
254 *createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateLargeWriteDAG;
255 } else {/* parity died, small write only updating Q */
256 if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
257 || (asmap->qInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
258 *createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateSmallWriteDAG;
259 else
260 *createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateLargeWriteDAG;
261 }
262 } else { /* data missing. Do a P reconstruct write if
263 * only a single data unit is lost in the
264 * stripe, otherwise a reconstruct write which
265 * employnig both P and E units. */
266 if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2) {
267 if (asmap->numStripeUnitsAccessed == 1)
268 *createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateWriteDAG;
269 else
270 *createFunc = NULL; /* No direct support for
271 * this case now, like
272 * that in Raid-5 */
273 } else {
274 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
275 *createFunc = NULL; /* No direct support for
276 * this case now, like
277 * that in Raid-5 */
278 else
279 *createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateWriteDAG;
280 }
281 }
282 break;
283
284 case 2: /* two disk faults */
285 switch (npfail) {
286 case 2: /* both p and q dead */
287 *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
288 break;
289 case 1: /* either p or q and dead data */
290 RF_ASSERT(asmap->failedPDAs[0]->type == RF_PDA_TYPE_DATA);
291 RF_ASSERT((asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
292 if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
293 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
294 *createFunc = NULL; /* In both PQ and
295 * EvenOdd, no direct
296 * support for this case
297 * now, like that in
298 * Raid-5 */
299 else
300 *createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateWriteDAG;
301 } else {
302 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
303 *createFunc = NULL; /* No direct support for
304 * this case, like that
305 * in Raid-5 */
306 else
307 *createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateWriteDAG;
308 }
309 break;
310 case 0: /* double data loss */
311 /* if(asmap->failedPDAs[0]->numSector +
312 * asmap->failedPDAs[1]->numSector == 2 *
313 * layoutPtr->sectorsPerStripeUnit ) createFunc =
314 * rf_EOCreateLargeWriteDAG; else */
315 *createFunc = NULL; /* currently, in Evenodd, No
316 * support for simultaneous
317 * access of both failed SUs */
318 break;
319 }
320 break;
321
322 default: /* more than 2 disk faults */
323 *createFunc = NULL;
324 RF_PANIC();
325 }
326 return;
327 }
328
329
330 int
331 rf_VerifyParityEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t raidAddr,
332 RF_PhysDiskAddr_t *parityPDA, int correct_it,
333 RF_RaidAccessFlags_t flags)
334 {
335 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
336 RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
337 RF_SectorCount_t numsector = parityPDA->numSector;
338 int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
339 int bytesPerStripe = numbytes * layoutPtr->numDataCol;
340 RF_DagHeader_t *rd_dag_h, *wr_dag_h; /* read, write dag */
341 RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
342 RF_AccessStripeMapHeader_t *asm_h;
343 RF_AccessStripeMap_t *asmap;
344 RF_AllocListElem_t *alloclist;
345 RF_PhysDiskAddr_t *pda;
346 char *pbuf, *buf, *end_p, *p;
347 char *redundantbuf2;
348 int redundantTwoErr = 0, redundantOneErr = 0;
349 int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
350 parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
351 int i, retcode;
352 RF_ReconUnitNum_t which_ru;
353 RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
354 int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
355 RF_AccTraceEntry_t tracerec;
356 RF_MCPair_t *mcpair;
357
358 retcode = RF_PARITY_OKAY;
359
360 mcpair = rf_AllocMCPair();
361 rf_MakeAllocList(alloclist);
362 RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol), (char *), alloclist);
363 RF_MallocAndAdd(pbuf, numbytes, (char *), alloclist);
364 end_p = buf + bytesPerStripe;
365 RF_MallocAndAdd(redundantbuf2, numbytes, (char *), alloclist);
366
367 rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc,
368 "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
369 blockNode = rd_dag_h->succedents[0];
370 unblockNode = blockNode->succedents[0]->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((char *) &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_MUTEX(mcpair->mutex);
416 mcpair->flag = 0;
417 rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
418 (void *) mcpair);
419 while (!mcpair->flag)
420 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
421 RF_UNLOCK_MUTEX(mcpair->mutex);
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 wrUnblock = wrBlock->succedents[0]->succedents[0];
466 wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
467 wrBlock->succedents[0]->params[2].v = psID;
468 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, which_ru);
469 memset((char *) &tracerec, 0, sizeof(tracerec));
470 wr_dag_h->tracerec = &tracerec;
471 #if RF_DEBUG_VALIDATE_DAG
472 if (rf_verifyParityDebug) {
473 printf("Parity verify write dag:\n");
474 rf_PrintDAGList(wr_dag_h);
475 }
476 #endif
477 RF_LOCK_MUTEX(mcpair->mutex);
478 mcpair->flag = 0;
479 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
480 (void *) mcpair);
481 while (!mcpair->flag)
482 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
483 RF_UNLOCK_MUTEX(mcpair->mutex);
484 if (wr_dag_h->status != rf_enable) {
485 RF_ERRORMSG("Unable to correct parity in VerifyParity: can't write the stripe\n");
486 parity_cant_correct = RF_TRUE;
487 } else {
488 parity_corrected = RF_TRUE;
489 }
490 rf_FreeDAG(wr_dag_h);
491 }
492 if (redundantTwoErr && correct_it) {
493 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
494 "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
495 wrBlock = wr_dag_h->succedents[0];
496 wrUnblock = wrBlock->succedents[0]->succedents[0];
497 wrBlock->succedents[0]->params[0].p = asmap->qInfo;
498 wrBlock->succedents[0]->params[2].v = psID;
499 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, which_ru);
500 memset((char *) &tracerec, 0, sizeof(tracerec));
501 wr_dag_h->tracerec = &tracerec;
502 #if RF_DEBUG_VALIDATE_DAG
503 if (rf_verifyParityDebug) {
504 printf("Dag of write new second redundant information in parity verify :\n");
505 rf_PrintDAGList(wr_dag_h);
506 }
507 #endif
508 RF_LOCK_MUTEX(mcpair->mutex);
509 mcpair->flag = 0;
510 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
511 (void *) mcpair);
512 while (!mcpair->flag)
513 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
514 RF_UNLOCK_MUTEX(mcpair->mutex);
515 if (wr_dag_h->status != rf_enable) {
516 RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n");
517 red2_cant_correct = RF_TRUE;
518 } else {
519 red2_corrected = RF_TRUE;
520 }
521 rf_FreeDAG(wr_dag_h);
522 }
523 if ((redundantOneErr && parity_cant_correct) ||
524 (redundantTwoErr && red2_cant_correct))
525 retcode = RF_PARITY_COULD_NOT_CORRECT;
526 if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
527 retcode = RF_PARITY_CORRECTED;
528
529
530 out:
531 rf_FreeAccessStripeMap(asm_h);
532 rf_FreeAllocList(alloclist);
533 rf_FreeDAG(rd_dag_h);
534 rf_FreeMCPair(mcpair);
535 return (retcode);
536 }
537 #endif /* RF_INCLUDE_EVENODD > 0 */
538