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