1 /* $NetBSD: rf_evenodd.c,v 1.18 2006/11/16 01:33:23 christos Exp $ */
3 * Copyright (c) 1995 Carnegie-Mellon University.
6 * Author: Chang-Ming Wu
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 /*****************************************************************************************
31 * rf_evenodd.c -- implements EVENODD array architecture
33 ****************************************************************************************/
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_evenodd.c,v 1.18 2006/11/16 01:33:23 christos Exp $");
40 #if RF_INCLUDE_EVENODD > 0
42 #include <dev/raidframe/raidframevar.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"
59 #include "rf_mcpair.h"
60 #include "rf_evenodd_dagfuncs.h"
61 #include "rf_evenodd_dags.h"
62 #include "rf_engine.h"
64 typedef struct RF_EvenOddConfigInfo_s
{
65 RF_RowCol_t
**stripeIdentifier
; /* filled in at config time & used by
67 } RF_EvenOddConfigInfo_t
;
70 rf_ConfigureEvenOdd(RF_ShutdownList_t
**listp
, RF_Raid_t
*raidPtr
,
73 RF_RaidLayout_t
*layoutPtr
= &raidPtr
->Layout
;
74 RF_EvenOddConfigInfo_t
*info
;
75 RF_RowCol_t i
, j
, startdisk
;
77 RF_MallocAndAdd(info
, sizeof(RF_EvenOddConfigInfo_t
), (RF_EvenOddConfigInfo_t
*), raidPtr
->cleanupList
);
78 layoutPtr
->layoutSpecificInfo
= (void *) info
;
80 info
->stripeIdentifier
= rf_make_2d_array(raidPtr
->numCol
, raidPtr
->numCol
, raidPtr
->cleanupList
);
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
;
86 if ((startdisk
-= 2) < 0)
87 startdisk
+= raidPtr
->numCol
;
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");
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");
110 layoutPtr
->dataSectorsPerStripe
= layoutPtr
->numDataCol
* layoutPtr
->sectorsPerStripeUnit
;
111 layoutPtr
->numParityCol
= 2;
112 layoutPtr
->dataStripeUnitsPerDisk
= layoutPtr
->stripeUnitsPerDisk
;
113 raidPtr
->sectorsPerDisk
= layoutPtr
->stripeUnitsPerDisk
* layoutPtr
->sectorsPerStripeUnit
;
115 raidPtr
->totalSectors
= layoutPtr
->stripeUnitsPerDisk
* layoutPtr
->numDataCol
* layoutPtr
->sectorsPerStripeUnit
;
121 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t
*raidPtr
)
127 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t
*raidPtr
)
133 rf_IdentifyStripeEvenOdd(RF_Raid_t
*raidPtr
, RF_RaidAddr_t addr
,
134 RF_RowCol_t
**diskids
)
136 RF_StripeNum_t stripeID
= rf_RaidAddressToStripeID(&raidPtr
->Layout
, addr
);
137 RF_EvenOddConfigInfo_t
*info
= (RF_EvenOddConfigInfo_t
*) raidPtr
->Layout
.layoutSpecificInfo
;
139 *diskids
= info
->stripeIdentifier
[stripeID
% raidPtr
->numCol
];
141 /* The layout of stripe unit on the disks are: c0 c1 c2 c3 c4
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.
157 rf_MapParityEvenOdd(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidSector
,
159 RF_SectorNum_t
*diskSector
, int remap
)
161 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
162 RF_StripeNum_t endSUIDofthisStrip
= (SUID
/ raidPtr
->Layout
.numDataCol
+ 1) * raidPtr
->Layout
.numDataCol
- 1;
164 *col
= (endSUIDofthisStrip
+ 2) % raidPtr
->numCol
;
165 *diskSector
= (SUID
/ (raidPtr
->Layout
.numDataCol
)) * raidPtr
->Layout
.sectorsPerStripeUnit
+
166 (raidSector
% raidPtr
->Layout
.sectorsPerStripeUnit
);
170 rf_MapEEvenOdd(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidSector
,
171 RF_RowCol_t
*col
, RF_SectorNum_t
*diskSector
,
174 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
175 RF_StripeNum_t endSUIDofthisStrip
= (SUID
/ raidPtr
->Layout
.numDataCol
+ 1) * raidPtr
->Layout
.numDataCol
- 1;
177 *col
= (endSUIDofthisStrip
+ 1) % raidPtr
->numCol
;
178 *diskSector
= (SUID
/ (raidPtr
->Layout
.numDataCol
)) * raidPtr
->Layout
.sectorsPerStripeUnit
+
179 (raidSector
% raidPtr
->Layout
.sectorsPerStripeUnit
);
183 rf_EODagSelect(RF_Raid_t
*raidPtr
, RF_IoType_t type
,
184 RF_AccessStripeMap_t
*asmap
, RF_VoidFuncPtr
*createFunc
)
186 RF_RaidLayout_t
*layoutPtr
= &(raidPtr
->Layout
);
187 unsigned ndfail
= asmap
->numDataFailed
;
188 unsigned npfail
= asmap
->numParityFailed
+ asmap
->numQFailed
;
189 unsigned ntfail
= npfail
+ ndfail
;
191 RF_ASSERT(RF_IO_IS_R_OR_W(type
));
193 RF_ERRORMSG("more than two disks failed in a single group! Aborting I/O operation.\n");
197 /* ok, we can do this I/O */
198 if (type
== RF_IO_TYPE_READ
) {
201 /* fault free read */
202 *createFunc
= (RF_VoidFuncPtr
) rf_CreateFaultFreeReadDAG
; /* same as raid 5 */
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
;
213 *createFunc
= (RF_VoidFuncPtr
) rf_EO_101_CreateReadDAG
;
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
;
220 *createFunc
= (RF_VoidFuncPtr
) rf_EO_100_CreateReadDAG
;
224 /* *createFunc = rf_EO_200_CreateReadDAG; */
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
))) {
237 *createFunc
= (RF_VoidFuncPtr
) rf_EOCreateSmallWriteDAG
;
239 *createFunc
= (RF_VoidFuncPtr
) rf_EOCreateLargeWriteDAG
;
243 case 1: /* single disk fault */
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
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
;
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
;
259 *createFunc
= (RF_VoidFuncPtr
) rf_EO_010_CreateLargeWriteDAG
;
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
;
269 *createFunc
= NULL
; /* No direct support for
270 * this case now, like
273 if (asmap
->numStripeUnitsAccessed
!= 1 && asmap
->failedPDAs
[0]->numSector
!= layoutPtr
->sectorsPerStripeUnit
)
274 *createFunc
= NULL
; /* No direct support for
275 * this case now, like
278 *createFunc
= (RF_VoidFuncPtr
) rf_EO_100_CreateWriteDAG
;
283 case 2: /* two disk faults */
285 case 2: /* both p and q dead */
286 *createFunc
= (RF_VoidFuncPtr
) rf_EO_011_CreateWriteDAG
;
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
295 * support for this case
299 *createFunc
= (RF_VoidFuncPtr
) rf_EO_101_CreateWriteDAG
;
301 if (asmap
->numStripeUnitsAccessed
!= 1 && asmap
->failedPDAs
[0]->numSector
!= layoutPtr
->sectorsPerStripeUnit
)
302 *createFunc
= NULL
; /* No direct support for
303 * this case, like that
306 *createFunc
= (RF_VoidFuncPtr
) rf_EO_110_CreateWriteDAG
;
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 */
321 default: /* more than 2 disk faults */
330 rf_VerifyParityEvenOdd(RF_Raid_t
*raidPtr
, RF_RaidAddr_t raidAddr
,
331 RF_PhysDiskAddr_t
*parityPDA
, int correct_it
,
332 RF_RaidAccessFlags_t flags
)
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
, *unblockNode
, *wrBlock
, *wrUnblock
;
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
;
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
;
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
;
357 retcode
= RF_PARITY_OKAY
;
359 mcpair
= rf_AllocMCPair();
360 rf_MakeAllocList(alloclist
);
361 RF_MallocAndAdd(buf
, numbytes
* (layoutPtr
->numDataCol
+ layoutPtr
->numParityCol
), (char *), alloclist
);
362 RF_MallocAndAdd(pbuf
, numbytes
, (char *), alloclist
);
363 end_p
= buf
+ bytesPerStripe
;
364 RF_MallocAndAdd(redundantbuf2
, numbytes
, (char *), alloclist
);
366 rd_dag_h
= rf_MakeSimpleDAG(raidPtr
, stripeWidth
, numbytes
, buf
, rf_DiskReadFunc
, rf_DiskReadUndoFunc
,
367 "Rod", alloclist
, flags
, RF_IO_NORMAL_PRIORITY
);
368 blockNode
= rd_dag_h
->succedents
[0];
369 unblockNode
= blockNode
->succedents
[0]->succedents
[0];
371 /* map the stripe and fill in the PDAs in the dag */
372 asm_h
= rf_MapAccess(raidPtr
, startAddr
, layoutPtr
->dataSectorsPerStripe
, buf
, RF_DONT_REMAP
);
373 asmap
= asm_h
->stripeMap
;
375 for (pda
= asmap
->physInfo
, i
= 0; i
< layoutPtr
->numDataCol
; i
++, pda
= pda
->next
) {
377 rf_RangeRestrictPDA(raidPtr
, parityPDA
, pda
, 0, 1);
378 RF_ASSERT(pda
->numSector
!= 0);
379 if (rf_TryToRedirectPDA(raidPtr
, pda
, 0))
380 goto out
; /* no way to verify parity if disk is
381 * dead. return w/ good status */
382 blockNode
->succedents
[i
]->params
[0].p
= pda
;
383 blockNode
->succedents
[i
]->params
[2].v
= psID
;
384 blockNode
->succedents
[i
]->params
[3].v
= RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY
, which_ru
);
387 RF_ASSERT(!asmap
->parityInfo
->next
);
388 rf_RangeRestrictPDA(raidPtr
, parityPDA
, asmap
->parityInfo
, 0, 1);
389 RF_ASSERT(asmap
->parityInfo
->numSector
!= 0);
390 if (rf_TryToRedirectPDA(raidPtr
, asmap
->parityInfo
, 1))
392 blockNode
->succedents
[layoutPtr
->numDataCol
]->params
[0].p
= asmap
->parityInfo
;
394 RF_ASSERT(!asmap
->qInfo
->next
);
395 rf_RangeRestrictPDA(raidPtr
, parityPDA
, asmap
->qInfo
, 0, 1);
396 RF_ASSERT(asmap
->qInfo
->numSector
!= 0);
397 if (rf_TryToRedirectPDA(raidPtr
, asmap
->qInfo
, 1))
399 /* if disk is dead, b/c no reconstruction is implemented right now,
400 * the function "rf_TryToRedirectPDA" always return one, which cause
401 * go to out and return w/ good status */
402 blockNode
->succedents
[layoutPtr
->numDataCol
+ 1]->params
[0].p
= asmap
->qInfo
;
404 /* fire off the DAG */
405 memset((char *) &tracerec
, 0, sizeof(tracerec
));
406 rd_dag_h
->tracerec
= &tracerec
;
408 #if RF_DEBUG_VALIDATE_DAG
409 if (rf_verifyParityDebug
) {
410 printf("Parity verify read dag:\n");
411 rf_PrintDAGList(rd_dag_h
);
414 RF_LOCK_MUTEX(mcpair
->mutex
);
416 rf_DispatchDAG(rd_dag_h
, (void (*) (void *)) rf_MCPairWakeupFunc
,
418 while (!mcpair
->flag
)
419 RF_WAIT_COND(mcpair
->cond
, mcpair
->mutex
);
420 RF_UNLOCK_MUTEX(mcpair
->mutex
);
421 if (rd_dag_h
->status
!= rf_enable
) {
422 RF_ERRORMSG("Unable to verify parity: can't read the stripe\n");
423 retcode
= RF_PARITY_COULD_NOT_VERIFY
;
426 for (p
= buf
, i
= 0; p
< end_p
; p
+= numbytes
, i
++) {
427 rf_e_encToBuf(raidPtr
, i
, p
, RF_EO_MATRIX_DIM
- 2, redundantbuf2
, numsector
);
428 /* the corresponding columes in EvenOdd encoding Matrix for
429 * these p pointers which point to the databuffer in a full
430 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */
431 rf_bxor(p
, pbuf
, numbytes
);
433 RF_ASSERT(i
== layoutPtr
->numDataCol
);
435 for (i
= 0; i
< numbytes
; i
++) {
436 if (pbuf
[i
] != buf
[bytesPerStripe
+ i
]) {
438 RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n",
439 i
, (u_char
) buf
[bytesPerStripe
+ i
], (u_char
) pbuf
[i
]);
446 for (i
= 0; i
< numbytes
; i
++) {
447 if (redundantbuf2
[i
] != buf
[bytesPerStripe
+ numbytes
+ i
]) {
449 RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n",
450 i
, (u_char
) buf
[bytesPerStripe
+ numbytes
+ i
], (u_char
) redundantbuf2
[i
]);
456 if (redundantOneErr
|| redundantTwoErr
)
457 retcode
= RF_PARITY_BAD
;
459 /* correct the first redundant disk, ie parity if it is error */
460 if (redundantOneErr
&& correct_it
) {
461 wr_dag_h
= rf_MakeSimpleDAG(raidPtr
, 1, numbytes
, pbuf
, rf_DiskWriteFunc
, rf_DiskWriteUndoFunc
,
462 "Wnp", alloclist
, flags
, RF_IO_NORMAL_PRIORITY
);
463 wrBlock
= wr_dag_h
->succedents
[0];
464 wrUnblock
= wrBlock
->succedents
[0]->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((char *) &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
);
476 RF_LOCK_MUTEX(mcpair
->mutex
);
478 rf_DispatchDAG(wr_dag_h
, (void (*) (void *)) rf_MCPairWakeupFunc
,
480 while (!mcpair
->flag
)
481 RF_WAIT_COND(mcpair
->cond
, mcpair
->mutex
);
482 RF_UNLOCK_MUTEX(mcpair
->mutex
);
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
;
487 parity_corrected
= RF_TRUE
;
489 rf_FreeDAG(wr_dag_h
);
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 wrUnblock
= wrBlock
->succedents
[0]->succedents
[0];
496 wrBlock
->succedents
[0]->params
[0].p
= asmap
->qInfo
;
497 wrBlock
->succedents
[0]->params
[2].v
= psID
;
498 wrBlock
->succedents
[0]->params
[3].v
= RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY
, which_ru
);
499 memset((char *) &tracerec
, 0, sizeof(tracerec
));
500 wr_dag_h
->tracerec
= &tracerec
;
501 #if RF_DEBUG_VALIDATE_DAG
502 if (rf_verifyParityDebug
) {
503 printf("Dag of write new second redundant information in parity verify :\n");
504 rf_PrintDAGList(wr_dag_h
);
507 RF_LOCK_MUTEX(mcpair
->mutex
);
509 rf_DispatchDAG(wr_dag_h
, (void (*) (void *)) rf_MCPairWakeupFunc
,
511 while (!mcpair
->flag
)
512 RF_WAIT_COND(mcpair
->cond
, mcpair
->mutex
);
513 RF_UNLOCK_MUTEX(mcpair
->mutex
);
514 if (wr_dag_h
->status
!= rf_enable
) {
515 RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n");
516 red2_cant_correct
= RF_TRUE
;
518 red2_corrected
= RF_TRUE
;
520 rf_FreeDAG(wr_dag_h
);
522 if ((redundantOneErr
&& parity_cant_correct
) ||
523 (redundantTwoErr
&& red2_cant_correct
))
524 retcode
= RF_PARITY_COULD_NOT_CORRECT
;
525 if ((retcode
= RF_PARITY_BAD
) && parity_corrected
&& red2_corrected
)
526 retcode
= RF_PARITY_CORRECTED
;
530 rf_FreeAccessStripeMap(asm_h
);
531 rf_FreeAllocList(alloclist
);
532 rf_FreeDAG(rd_dag_h
);
533 rf_FreeMCPair(mcpair
);
536 #endif /* RF_INCLUDE_EVENODD > 0 */