This source file includes following definitions.
- RF_EvenOddConfigInfo_t
- rf_ConfigureEvenOdd
- rf_GetDefaultNumFloatingReconBuffersEvenOdd
- rf_GetDefaultHeadSepLimitEvenOdd
- rf_IdentifyStripeEvenOdd
- rf_MapParityEvenOdd
- rf_MapEEvenOdd
- rf_EODagSelect
- rf_VerifyParityEvenOdd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include "rf_archs.h"
38
39 #if RF_INCLUDE_EVENODD > 0
40
41 #include "rf_types.h"
42 #include "rf_raid.h"
43 #include "rf_dag.h"
44 #include "rf_dagffrd.h"
45 #include "rf_dagffwr.h"
46 #include "rf_dagdegrd.h"
47 #include "rf_dagdegwr.h"
48 #include "rf_dagutils.h"
49 #include "rf_dagfuncs.h"
50 #include "rf_etimer.h"
51 #include "rf_general.h"
52 #include "rf_evenodd.h"
53 #include "rf_configure.h"
54 #include "rf_parityscan.h"
55 #include "rf_utils.h"
56 #include "rf_map.h"
57 #include "rf_pq.h"
58 #include "rf_mcpair.h"
59 #include "rf_evenodd.h"
60 #include "rf_evenodd_dagfuncs.h"
61 #include "rf_evenodd_dags.h"
62 #include "rf_engine.h"
63
64 typedef struct RF_EvenOddConfigInfo_s {
65 RF_RowCol_t **stripeIdentifier;
66
67
68
69 } RF_EvenOddConfigInfo_t;
70
71 int
72 rf_ConfigureEvenOdd(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
73 RF_Config_t *cfgPtr)
74 {
75 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
76 RF_EvenOddConfigInfo_t *info;
77 RF_RowCol_t i, j, startdisk;
78
79 RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t),
80 (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
81 layoutPtr->layoutSpecificInfo = (void *) info;
82
83 RF_ASSERT(raidPtr->numRow == 1);
84
85 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol,
86 raidPtr->numCol, raidPtr->cleanupList);
87 startdisk = 0;
88 for (i = 0; i < raidPtr->numCol; i++) {
89 for (j = 0; j < raidPtr->numCol; j++) {
90 info->stripeIdentifier[i][j] = (startdisk + j) %
91 raidPtr->numCol;
92 }
93 if ((startdisk -= 2) < 0)
94 startdisk += raidPtr->numCol;
95 }
96
97
98 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
99 layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
100 raidPtr->logBytesPerSector;
101 layoutPtr->numDataCol = raidPtr->numCol - 2;
102
103
104
105
106 #if RF_EO_MATRIX_DIM > 17
107 if (raidPtr->numCol <= 17) {
108 printf("Number of stripe units in a parity stripe is smaller"
109 " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
110 " file rf_evenodd_dagfuncs.h to\nbe 17 to increase"
111 " performance.\n");
112 return (EINVAL);
113 }
114 #elif RF_EO_MATRIX_DIM == 17
115 if (raidPtr->numCol > 17) {
116 printf("Number of stripe units in a parity stripe is bigger"
117 " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
118 " file rf_evenodd_dagfuncs.h to\nbe 257 for encoding and"
119 " decoding functions to work.\n");
120 return (EINVAL);
121 }
122 #endif
123 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
124 layoutPtr->sectorsPerStripeUnit;
125 layoutPtr->numParityCol = 2;
126 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
127 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
128 layoutPtr->sectorsPerStripeUnit;
129
130 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
131 layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
132
133 return (0);
134 }
135
136 int
137 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr)
138 {
139 return (20);
140 }
141
142 RF_HeadSepLimit_t
143 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr)
144 {
145 return (10);
146 }
147
148 void
149 rf_IdentifyStripeEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
150 RF_RowCol_t **diskids, RF_RowCol_t *outRow)
151 {
152 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
153 addr);
154 RF_EvenOddConfigInfo_t *info =
155 (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
156
157 *outRow = 0;
158 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 void
181 rf_MapParityEvenOdd(
182 RF_Raid_t *raidPtr,
183 RF_RaidAddr_t raidSector,
184 RF_RowCol_t *row,
185 RF_RowCol_t *col,
186 RF_SectorNum_t *diskSector,
187 int remap
188 )
189 {
190 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
191 RF_StripeNum_t endSUIDofthisStrip =
192 (SUID / raidPtr->Layout.numDataCol + 1) *
193 raidPtr->Layout.numDataCol - 1;
194
195 *row = 0;
196 *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
197 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
198 raidPtr->Layout.sectorsPerStripeUnit +
199 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
200 }
201
202 void
203 rf_MapEEvenOdd(
204 RF_Raid_t *raidPtr,
205 RF_RaidAddr_t raidSector,
206 RF_RowCol_t *row,
207 RF_RowCol_t *col,
208 RF_SectorNum_t *diskSector,
209 int remap
210 )
211 {
212 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
213 RF_StripeNum_t endSUIDofthisStrip =
214 (SUID / raidPtr->Layout.numDataCol + 1) *
215 raidPtr->Layout.numDataCol - 1;
216
217 *row = 0;
218 *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
219 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
220 raidPtr->Layout.sectorsPerStripeUnit +
221 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
222 }
223
224 void
225 rf_EODagSelect(
226 RF_Raid_t *raidPtr,
227 RF_IoType_t type,
228 RF_AccessStripeMap_t *asmap,
229 RF_VoidFuncPtr *createFunc
230 )
231 {
232 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
233 unsigned ndfail = asmap->numDataFailed;
234 unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
235 unsigned ntfail = npfail + ndfail;
236
237 RF_ASSERT(RF_IO_IS_R_OR_W(type));
238 if (ntfail > 2) {
239 RF_ERRORMSG("more than two disks failed in a single group !"
240 " Aborting I/O operation.\n");
241 *createFunc = NULL;
242 return;
243 }
244
245 if (type == RF_IO_TYPE_READ) {
246 switch (ndfail) {
247 case 0:
248
249 *createFunc = (RF_VoidFuncPtr)
250 rf_CreateFaultFreeReadDAG;
251 break;
252 case 1:
253
254
255
256
257
258
259
260 if (ntfail == 2) {
261 if (asmap->failedPDAs[1]->type ==
262 RF_PDA_TYPE_PARITY)
263 *createFunc = (RF_VoidFuncPtr)
264 rf_EO_110_CreateReadDAG;
265 else
266 *createFunc = (RF_VoidFuncPtr)
267 rf_EO_101_CreateReadDAG;
268 } else {
269
270
271
272
273 if (rf_NumFailedDataUnitsInStripe(raidPtr,
274 asmap) == 2)
275 *createFunc = (RF_VoidFuncPtr)
276 rf_EO_200_CreateReadDAG;
277 else
278 *createFunc = (RF_VoidFuncPtr)
279 rf_EO_100_CreateReadDAG;
280 }
281 break;
282 case 2:
283
284 *createFunc = NULL;
285 break;
286 }
287 return;
288 }
289
290 switch (ntfail) {
291 case 0:
292 if (rf_suppressLocksAndLargeWrites ||
293 (((asmap->numStripeUnitsAccessed <=
294 (layoutPtr->numDataCol / 2)) &&
295 (layoutPtr->numDataCol != 1)) ||
296 (asmap->parityInfo->next != NULL) ||
297 (asmap->qInfo->next != NULL) ||
298 rf_CheckStripeForFailures(raidPtr, asmap))) {
299
300 *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
301 } else {
302 *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
303 }
304 break;
305
306 case 1:
307 if (npfail == 1) {
308 RF_ASSERT((asmap->failedPDAs[0]->type ==
309 RF_PDA_TYPE_PARITY) ||
310 (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
311 if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {
312
313
314
315
316 if (((asmap->numStripeUnitsAccessed <=
317 (layoutPtr->numDataCol / 2)) ||
318 (asmap->numStripeUnitsAccessed == 1)) ||
319 (asmap->parityInfo->next != NULL) ||
320 rf_NumFailedDataUnitsInStripe(raidPtr,
321 asmap))
322 *createFunc = (RF_VoidFuncPtr)
323 rf_EO_001_CreateSmallWriteDAG;
324 else
325 *createFunc = (RF_VoidFuncPtr)
326 rf_EO_001_CreateLargeWriteDAG;
327 } else {
328
329 if (((asmap->numStripeUnitsAccessed <=
330 (layoutPtr->numDataCol / 2)) ||
331 (asmap->numStripeUnitsAccessed == 1)) ||
332 (asmap->qInfo->next != NULL) ||
333 rf_NumFailedDataUnitsInStripe(raidPtr,
334 asmap))
335 *createFunc = (RF_VoidFuncPtr)
336 rf_EO_010_CreateSmallWriteDAG;
337 else
338 *createFunc = (RF_VoidFuncPtr)
339 rf_EO_010_CreateLargeWriteDAG;
340 }
341 } else {
342
343
344
345
346
347 if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
348 {
349 if (asmap->numStripeUnitsAccessed == 1)
350 *createFunc = (RF_VoidFuncPtr)
351 rf_EO_200_CreateWriteDAG;
352 else
353
354
355
356
357 *createFunc = NULL;
358 } else {
359 if (asmap->numStripeUnitsAccessed != 1 &&
360 asmap->failedPDAs[0]->numSector !=
361 layoutPtr->sectorsPerStripeUnit)
362
363
364
365
366 *createFunc = NULL;
367 else
368 *createFunc = (RF_VoidFuncPtr)
369 rf_EO_100_CreateWriteDAG;
370 }
371 }
372 break;
373
374 case 2:
375 switch (npfail) {
376 case 2:
377 *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
378 break;
379 case 1:
380 RF_ASSERT(asmap->failedPDAs[0]->type ==
381 RF_PDA_TYPE_DATA);
382 RF_ASSERT((asmap->failedPDAs[1]->type ==
383 RF_PDA_TYPE_PARITY) ||
384 (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
385 if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
386 if (asmap->numStripeUnitsAccessed != 1 &&
387 asmap->failedPDAs[0]->numSector !=
388 layoutPtr->sectorsPerStripeUnit)
389
390
391
392
393
394 *createFunc = NULL;
395 else
396 *createFunc = (RF_VoidFuncPtr)
397 rf_EO_101_CreateWriteDAG;
398 } else {
399 if (asmap->numStripeUnitsAccessed != 1 &&
400 asmap->failedPDAs[0]->numSector !=
401 layoutPtr->sectorsPerStripeUnit)
402
403
404
405
406 *createFunc = NULL;
407 else
408 *createFunc = (RF_VoidFuncPtr)
409 rf_EO_110_CreateWriteDAG;
410 }
411 break;
412 case 0:
413
414
415
416
417
418
419 *createFunc = NULL;
420
421
422
423
424 break;
425 }
426 break;
427
428 default:
429 *createFunc = NULL;
430 RF_PANIC();
431 }
432 return;
433 }
434
435
436 int
437 rf_VerifyParityEvenOdd(
438 RF_Raid_t *raidPtr,
439 RF_RaidAddr_t raidAddr,
440 RF_PhysDiskAddr_t *parityPDA,
441 int correct_it,
442 RF_RaidAccessFlags_t flags
443 )
444 {
445 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
446 RF_RaidAddr_t startAddr =
447 rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
448 RF_SectorCount_t numsector = parityPDA->numSector;
449 int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
450 int bytesPerStripe = numbytes * layoutPtr->numDataCol;
451 RF_DagHeader_t *rd_dag_h, *wr_dag_h;
452 RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
453 RF_AccessStripeMapHeader_t *asm_h;
454 RF_AccessStripeMap_t *asmap;
455 RF_AllocListElem_t *alloclist;
456 RF_PhysDiskAddr_t *pda;
457 char *pbuf, *buf, *end_p, *p;
458 char *redundantbuf2;
459 int redundantTwoErr = 0, redundantOneErr = 0;
460 int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
461 parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
462 int i, retcode;
463 RF_ReconUnitNum_t which_ru;
464 RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr,
465 raidAddr, &which_ru);
466 int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
467 RF_AccTraceEntry_t tracerec;
468 RF_MCPair_t *mcpair;
469
470 retcode = RF_PARITY_OKAY;
471
472 mcpair = rf_AllocMCPair();
473 rf_MakeAllocList(alloclist);
474 RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol +
475 layoutPtr->numParityCol), (char *), alloclist);
476
477 RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
478 end_p = buf + bytesPerStripe;
479
480 RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);
481
482 rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf,
483 rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", alloclist, flags,
484 RF_IO_NORMAL_PRIORITY);
485 blockNode = rd_dag_h->succedents[0];
486 unblockNode = blockNode->succedents[0]->succedents[0];
487
488
489 asm_h = rf_MapAccess(raidPtr, startAddr,
490 layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
491 asmap = asm_h->stripeMap;
492
493 for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol;
494 i++, pda = pda->next) {
495 RF_ASSERT(pda);
496 rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
497 RF_ASSERT(pda->numSector != 0);
498 if (rf_TryToRedirectPDA(raidPtr, pda, 0))
499
500
501
502
503 goto out;
504 blockNode->succedents[i]->params[0].p = pda;
505 blockNode->succedents[i]->params[2].v = psID;
506 blockNode->succedents[i]->params[3].v =
507 RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
508 }
509
510 RF_ASSERT(!asmap->parityInfo->next);
511 rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
512 RF_ASSERT(asmap->parityInfo->numSector != 0);
513 if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
514 goto out;
515 blockNode->succedents[layoutPtr->numDataCol]->params[0].p =
516 asmap->parityInfo;
517
518 RF_ASSERT(!asmap->qInfo->next);
519 rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
520 RF_ASSERT(asmap->qInfo->numSector != 0);
521 if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
522 goto out;
523
524
525
526
527
528 blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p =
529 asmap->qInfo;
530
531
532 bzero((char *) &tracerec, sizeof(tracerec));
533 rd_dag_h->tracerec = &tracerec;
534
535 if (rf_verifyParityDebug) {
536 printf("Parity verify read dag:\n");
537 rf_PrintDAGList(rd_dag_h);
538 }
539 RF_LOCK_MUTEX(mcpair->mutex);
540 mcpair->flag = 0;
541 rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
542 (void *) mcpair);
543 while (!mcpair->flag)
544 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
545 RF_UNLOCK_MUTEX(mcpair->mutex);
546 if (rd_dag_h->status != rf_enable) {
547 RF_ERRORMSG("Unable to verify parity: can't read"
548 " the stripe\n");
549 retcode = RF_PARITY_COULD_NOT_VERIFY;
550 goto out;
551 }
552 for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
553 rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2,
554 redundantbuf2, numsector);
555
556
557
558
559
560 rf_bxor(p, pbuf, numbytes, NULL);
561 }
562 RF_ASSERT(i == layoutPtr->numDataCol);
563
564 for (i = 0; i < numbytes; i++) {
565 if (pbuf[i] != buf[bytesPerStripe + i]) {
566 if (!correct_it) {
567 RF_ERRORMSG3("Parity verify error: byte %d of"
568 " parity is 0x%x should be 0x%x\n", i,
569 (u_char) buf[bytesPerStripe + i],
570 (u_char) pbuf[i]);
571 }
572 }
573 redundantOneErr = 1;
574 break;
575 }
576
577 for (i = 0; i < numbytes; i++) {
578 if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
579 if (!correct_it) {
580 RF_ERRORMSG3("Parity verify error: byte %d of"
581 " second redundant information is 0x%x"
582 " should be 0x%x\n", i,
583 (u_char) buf[bytesPerStripe + numbytes + i],
584 (u_char) redundantbuf2[i]);
585 }
586 redundantTwoErr = 1;
587 break;
588 }
589 }
590 if (redundantOneErr || redundantTwoErr)
591 retcode = RF_PARITY_BAD;
592
593
594 if (redundantOneErr && correct_it) {
595 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf,
596 rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", alloclist,
597 flags, RF_IO_NORMAL_PRIORITY);
598 wrBlock = wr_dag_h->succedents[0];
599 wrUnblock = wrBlock->succedents[0]->succedents[0];
600 wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
601 wrBlock->succedents[0]->params[2].v = psID;
602 wrBlock->succedents[0]->params[3].v =
603 RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
604 bzero((char *) &tracerec, sizeof(tracerec));
605 wr_dag_h->tracerec = &tracerec;
606 if (rf_verifyParityDebug) {
607 printf("Parity verify write dag:\n");
608 rf_PrintDAGList(wr_dag_h);
609 }
610 RF_LOCK_MUTEX(mcpair->mutex);
611 mcpair->flag = 0;
612 rf_DispatchDAG(wr_dag_h,
613 (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
614 while (!mcpair->flag)
615 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
616 RF_UNLOCK_MUTEX(mcpair->mutex);
617 if (wr_dag_h->status != rf_enable) {
618 RF_ERRORMSG("Unable to correct parity in VerifyParity:"
619 " can't write the stripe\n");
620 parity_cant_correct = RF_TRUE;
621 } else {
622 parity_corrected = RF_TRUE;
623 }
624 rf_FreeDAG(wr_dag_h);
625 }
626 if (redundantTwoErr && correct_it) {
627 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes,
628 redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
629 "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
630 wrBlock = wr_dag_h->succedents[0];
631 wrUnblock = wrBlock->succedents[0]->succedents[0];
632 wrBlock->succedents[0]->params[0].p = asmap->qInfo;
633 wrBlock->succedents[0]->params[2].v = psID;
634 wrBlock->succedents[0]->params[3].v =
635 RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
636 bzero((char *) &tracerec, sizeof(tracerec));
637 wr_dag_h->tracerec = &tracerec;
638 if (rf_verifyParityDebug) {
639 printf("Dag of write new second redundant information"
640 " in parity verify :\n");
641 rf_PrintDAGList(wr_dag_h);
642 }
643 RF_LOCK_MUTEX(mcpair->mutex);
644 mcpair->flag = 0;
645 rf_DispatchDAG(wr_dag_h,
646 (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
647 while (!mcpair->flag)
648 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
649 RF_UNLOCK_MUTEX(mcpair->mutex);
650 if (wr_dag_h->status != rf_enable) {
651 RF_ERRORMSG("Unable to correct second redundant"
652 " information in VerifyParity: can't write the"
653 " stripe\n");
654 red2_cant_correct = RF_TRUE;
655 } else {
656 red2_corrected = RF_TRUE;
657 }
658 rf_FreeDAG(wr_dag_h);
659 }
660 if ((redundantOneErr && parity_cant_correct) ||
661 (redundantTwoErr && red2_cant_correct))
662 retcode = RF_PARITY_COULD_NOT_CORRECT;
663 if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
664 retcode = RF_PARITY_CORRECTED;
665
666
667 out:
668 rf_FreeAccessStripeMap(asm_h);
669 rf_FreeAllocList(alloclist);
670 rf_FreeDAG(rd_dag_h);
671 rf_FreeMCPair(mcpair);
672 return (retcode);
673 }
674 #endif