rf_evenodd.c revision 1.10 1 /* $NetBSD: rf_evenodd.c,v 1.10 2003/11/16 20:32:05 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 <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_evenodd.c,v 1.10 2003/11/16 20:32:05 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.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(listp, raidPtr, cfgPtr)
72 RF_ShutdownList_t **listp;
73 RF_Raid_t *raidPtr;
74 RF_Config_t *cfgPtr;
75 {
76 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
77 RF_EvenOddConfigInfo_t *info;
78 RF_RowCol_t i, j, startdisk;
79
80 RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (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, raidPtr->numCol, raidPtr->cleanupList);
86 startdisk = 0;
87 for (i = 0; i < raidPtr->numCol; i++) {
88 for (j = 0; j < raidPtr->numCol; j++) {
89 info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol;
90 }
91 if ((startdisk -= 2) < 0)
92 startdisk += raidPtr->numCol;
93 }
94
95 /* fill in the remaining layout parameters */
96 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
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 *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 memset((char *) &tracerec, 0, sizeof(tracerec));
433 rd_dag_h->tracerec = &tracerec;
434
435 #if RF_DEBUG_VALIDATE_DAG
436 if (rf_verifyParityDebug) {
437 printf("Parity verify read dag:\n");
438 rf_PrintDAGList(rd_dag_h);
439 }
440 #endif
441 RF_LOCK_MUTEX(mcpair->mutex);
442 mcpair->flag = 0;
443 rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
444 (void *) mcpair);
445 while (!mcpair->flag)
446 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
447 RF_UNLOCK_MUTEX(mcpair->mutex);
448 if (rd_dag_h->status != rf_enable) {
449 RF_ERRORMSG("Unable to verify parity: can't read the stripe\n");
450 retcode = RF_PARITY_COULD_NOT_VERIFY;
451 goto out;
452 }
453 for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
454 rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector);
455 /* the corresponding columes in EvenOdd encoding Matrix for
456 * these p pointers which point to the databuffer in a full
457 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */
458 rf_bxor(p, pbuf, numbytes, NULL);
459 }
460 RF_ASSERT(i == layoutPtr->numDataCol);
461
462 for (i = 0; i < numbytes; i++) {
463 if (pbuf[i] != buf[bytesPerStripe + i]) {
464 if (!correct_it) {
465 RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n",
466 i, (u_char) buf[bytesPerStripe + i], (u_char) pbuf[i]);
467 }
468 }
469 redundantOneErr = 1;
470 break;
471 }
472
473 for (i = 0; i < numbytes; i++) {
474 if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
475 if (!correct_it) {
476 RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n",
477 i, (u_char) buf[bytesPerStripe + numbytes + i], (u_char) redundantbuf2[i]);
478 }
479 redundantTwoErr = 1;
480 break;
481 }
482 }
483 if (redundantOneErr || redundantTwoErr)
484 retcode = RF_PARITY_BAD;
485
486 /* correct the first redundant disk, ie parity if it is error */
487 if (redundantOneErr && correct_it) {
488 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
489 "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY);
490 wrBlock = wr_dag_h->succedents[0];
491 wrUnblock = wrBlock->succedents[0]->succedents[0];
492 wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
493 wrBlock->succedents[0]->params[2].v = psID;
494 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
495 memset((char *) &tracerec, 0, sizeof(tracerec));
496 wr_dag_h->tracerec = &tracerec;
497 #if RF_DEBUG_VALIDATE_DAG
498 if (rf_verifyParityDebug) {
499 printf("Parity verify write dag:\n");
500 rf_PrintDAGList(wr_dag_h);
501 }
502 #endif
503 RF_LOCK_MUTEX(mcpair->mutex);
504 mcpair->flag = 0;
505 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
506 (void *) mcpair);
507 while (!mcpair->flag)
508 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
509 RF_UNLOCK_MUTEX(mcpair->mutex);
510 if (wr_dag_h->status != rf_enable) {
511 RF_ERRORMSG("Unable to correct parity in VerifyParity: can't write the stripe\n");
512 parity_cant_correct = RF_TRUE;
513 } else {
514 parity_corrected = RF_TRUE;
515 }
516 rf_FreeDAG(wr_dag_h);
517 }
518 if (redundantTwoErr && correct_it) {
519 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
520 "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
521 wrBlock = wr_dag_h->succedents[0];
522 wrUnblock = wrBlock->succedents[0]->succedents[0];
523 wrBlock->succedents[0]->params[0].p = asmap->qInfo;
524 wrBlock->succedents[0]->params[2].v = psID;
525 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
526 memset((char *) &tracerec, 0, sizeof(tracerec));
527 wr_dag_h->tracerec = &tracerec;
528 #if RF_DEBUG_VALIDATE_DAG
529 if (rf_verifyParityDebug) {
530 printf("Dag of write new second redundant information in parity verify :\n");
531 rf_PrintDAGList(wr_dag_h);
532 }
533 #endif
534 RF_LOCK_MUTEX(mcpair->mutex);
535 mcpair->flag = 0;
536 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
537 (void *) mcpair);
538 while (!mcpair->flag)
539 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
540 RF_UNLOCK_MUTEX(mcpair->mutex);
541 if (wr_dag_h->status != rf_enable) {
542 RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n");
543 red2_cant_correct = RF_TRUE;
544 } else {
545 red2_corrected = RF_TRUE;
546 }
547 rf_FreeDAG(wr_dag_h);
548 }
549 if ((redundantOneErr && parity_cant_correct) ||
550 (redundantTwoErr && red2_cant_correct))
551 retcode = RF_PARITY_COULD_NOT_CORRECT;
552 if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
553 retcode = RF_PARITY_CORRECTED;
554
555
556 out:
557 rf_FreeAccessStripeMap(asm_h);
558 rf_FreeAllocList(alloclist);
559 rf_FreeDAG(rd_dag_h);
560 rf_FreeMCPair(mcpair);
561 return (retcode);
562 }
563 #endif /* RF_INCLUDE_EVENODD > 0 */
564