rf_evenodd.c revision 1.4.6.3 1 /* $NetBSD: rf_evenodd.c,v 1.4.6.3 2001/11/14 19:15:48 nathanw 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.4.6.3 2001/11/14 19:15:48 nathanw 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->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector;
98 layoutPtr->numDataCol = raidPtr->numCol - 2; /* ORIG:
99 * layoutPtr->numDataCol
100 * = raidPtr->numCol-1; */
101 #if RF_EO_MATRIX_DIM > 17
102 if (raidPtr->numCol <= 17) {
103 printf("Number of stripe units in a parity stripe is smaller than 17. Please\n");
104 printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
105 printf("be 17 to increase performance. \n");
106 return (EINVAL);
107 }
108 #elif RF_EO_MATRIX_DIM == 17
109 if (raidPtr->numCol > 17) {
110 printf("Number of stripe units in a parity stripe is bigger than 17. Please\n");
111 printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
112 printf("be 257 for encoding and decoding functions to work. \n");
113 return (EINVAL);
114 }
115 #endif
116 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
117 layoutPtr->numParityCol = 2;
118 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
119 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
120
121 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
122
123 return (0);
124 }
125
126 int
127 rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t * raidPtr)
128 {
129 return (20);
130 }
131
132 RF_HeadSepLimit_t
133 rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t * raidPtr)
134 {
135 return (10);
136 }
137
138 void
139 rf_IdentifyStripeEvenOdd(
140 RF_Raid_t * raidPtr,
141 RF_RaidAddr_t addr,
142 RF_RowCol_t ** diskids,
143 RF_RowCol_t * outRow)
144 {
145 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
146 RF_EvenOddConfigInfo_t *info = (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
147
148 *outRow = 0;
149 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
150 }
151 /* The layout of stripe unit on the disks are: c0 c1 c2 c3 c4
152
153 0 1 2 E P
154 5 E P 3 4
155 P 6 7 8 E
156 10 11 E P 9
157 E P 12 13 14
158 ....
159
160 We use the MapSectorRAID5 to map data information because the routine can be shown to map exactly
161 the layout of data stripe unit as shown above although we have 2 redundant information now.
162 But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are different method from raid-5.
163 */
164
165
166 void
167 rf_MapParityEvenOdd(
168 RF_Raid_t * raidPtr,
169 RF_RaidAddr_t raidSector,
170 RF_RowCol_t * row,
171 RF_RowCol_t * col,
172 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 *row = 0;
179 *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
180 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
181 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
182 }
183
184 void
185 rf_MapEEvenOdd(
186 RF_Raid_t * raidPtr,
187 RF_RaidAddr_t raidSector,
188 RF_RowCol_t * row,
189 RF_RowCol_t * col,
190 RF_SectorNum_t * diskSector,
191 int remap)
192 {
193 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
194 RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
195
196 *row = 0;
197 *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
198 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
199 (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
200 }
201
202 void
203 rf_EODagSelect(
204 RF_Raid_t * raidPtr,
205 RF_IoType_t type,
206 RF_AccessStripeMap_t * asmap,
207 RF_VoidFuncPtr * createFunc)
208 {
209 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
210 unsigned ndfail = asmap->numDataFailed;
211 unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
212 unsigned ntfail = npfail + ndfail;
213
214 RF_ASSERT(RF_IO_IS_R_OR_W(type));
215 if (ntfail > 2) {
216 RF_ERRORMSG("more than two disks failed in a single group! Aborting I/O operation.\n");
217 /* *infoFunc = */ *createFunc = NULL;
218 return;
219 }
220 /* ok, we can do this I/O */
221 if (type == RF_IO_TYPE_READ) {
222 switch (ndfail) {
223 case 0:
224 /* fault free read */
225 *createFunc = (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG; /* same as raid 5 */
226 break;
227 case 1:
228 /* lost a single data unit */
229 /* two cases: (1) parity is not lost. do a normal raid
230 * 5 reconstruct read. (2) parity is lost. do a
231 * reconstruct read using "e". */
232 if (ntfail == 2) { /* also lost redundancy */
233 if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY)
234 *createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateReadDAG;
235 else
236 *createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateReadDAG;
237 } else {
238 /* P and E are ok. But is there a failure in
239 * some unaccessed data unit? */
240 if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
241 *createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateReadDAG;
242 else
243 *createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateReadDAG;
244 }
245 break;
246 case 2:
247 /* *createFunc = rf_EO_200_CreateReadDAG; */
248 *createFunc = NULL;
249 break;
250 }
251 return;
252 }
253 /* a write */
254 switch (ntfail) {
255 case 0: /* fault free */
256 if (rf_suppressLocksAndLargeWrites ||
257 (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) && (layoutPtr->numDataCol != 1)) ||
258 (asmap->parityInfo->next != NULL) || (asmap->qInfo->next != NULL) || rf_CheckStripeForFailures(raidPtr, asmap))) {
259
260 *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
261 } else {
262 *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
263 }
264 break;
265
266 case 1: /* single disk fault */
267 if (npfail == 1) {
268 RF_ASSERT((asmap->failedPDAs[0]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
269 if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) { /* q died, treat like
270 * normal mode raid5
271 * write. */
272 if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
273 || (asmap->parityInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
274 *createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateSmallWriteDAG;
275 else
276 *createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateLargeWriteDAG;
277 } else {/* parity died, small write only updating Q */
278 if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
279 || (asmap->qInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
280 *createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateSmallWriteDAG;
281 else
282 *createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateLargeWriteDAG;
283 }
284 } else { /* data missing. Do a P reconstruct write if
285 * only a single data unit is lost in the
286 * stripe, otherwise a reconstruct write which
287 * employnig both P and E units. */
288 if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2) {
289 if (asmap->numStripeUnitsAccessed == 1)
290 *createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateWriteDAG;
291 else
292 *createFunc = NULL; /* No direct support for
293 * this case now, like
294 * that in Raid-5 */
295 } else {
296 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
297 *createFunc = NULL; /* No direct support for
298 * this case now, like
299 * that in Raid-5 */
300 else
301 *createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateWriteDAG;
302 }
303 }
304 break;
305
306 case 2: /* two disk faults */
307 switch (npfail) {
308 case 2: /* both p and q dead */
309 *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
310 break;
311 case 1: /* either p or q and dead data */
312 RF_ASSERT(asmap->failedPDAs[0]->type == RF_PDA_TYPE_DATA);
313 RF_ASSERT((asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
314 if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
315 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
316 *createFunc = NULL; /* In both PQ and
317 * EvenOdd, no direct
318 * support for this case
319 * now, like that in
320 * Raid-5 */
321 else
322 *createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateWriteDAG;
323 } else {
324 if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
325 *createFunc = NULL; /* No direct support for
326 * this case, like that
327 * in Raid-5 */
328 else
329 *createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateWriteDAG;
330 }
331 break;
332 case 0: /* double data loss */
333 /* if(asmap->failedPDAs[0]->numSector +
334 * asmap->failedPDAs[1]->numSector == 2 *
335 * layoutPtr->sectorsPerStripeUnit ) createFunc =
336 * rf_EOCreateLargeWriteDAG; else */
337 *createFunc = NULL; /* currently, in Evenodd, No
338 * support for simultaneous
339 * access of both failed SUs */
340 break;
341 }
342 break;
343
344 default: /* more than 2 disk faults */
345 *createFunc = NULL;
346 RF_PANIC();
347 }
348 return;
349 }
350
351
352 int
353 rf_VerifyParityEvenOdd(raidPtr, raidAddr, parityPDA, correct_it, flags)
354 RF_Raid_t *raidPtr;
355 RF_RaidAddr_t raidAddr;
356 RF_PhysDiskAddr_t *parityPDA;
357 int correct_it;
358 RF_RaidAccessFlags_t flags;
359 {
360 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
361 RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
362 RF_SectorCount_t numsector = parityPDA->numSector;
363 int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
364 int bytesPerStripe = numbytes * layoutPtr->numDataCol;
365 RF_DagHeader_t *rd_dag_h, *wr_dag_h; /* read, write dag */
366 RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
367 RF_AccessStripeMapHeader_t *asm_h;
368 RF_AccessStripeMap_t *asmap;
369 RF_AllocListElem_t *alloclist;
370 RF_PhysDiskAddr_t *pda;
371 char *pbuf, *buf, *end_p, *p;
372 char *redundantbuf2;
373 int redundantTwoErr = 0, redundantOneErr = 0;
374 int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
375 parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
376 int i, retcode;
377 RF_ReconUnitNum_t which_ru;
378 RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
379 int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
380 RF_AccTraceEntry_t tracerec;
381 RF_MCPair_t *mcpair;
382
383 retcode = RF_PARITY_OKAY;
384
385 mcpair = rf_AllocMCPair();
386 rf_MakeAllocList(alloclist);
387 RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol), (char *), alloclist);
388 RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist); /* use calloc to make
389 * sure buffer is zeroed */
390 end_p = buf + bytesPerStripe;
391 RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist); /* use calloc to make
392 * sure buffer is zeroed */
393
394 rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc,
395 "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
396 blockNode = rd_dag_h->succedents[0];
397 unblockNode = blockNode->succedents[0]->succedents[0];
398
399 /* map the stripe and fill in the PDAs in the dag */
400 asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
401 asmap = asm_h->stripeMap;
402
403 for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol; i++, pda = pda->next) {
404 RF_ASSERT(pda);
405 rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
406 RF_ASSERT(pda->numSector != 0);
407 if (rf_TryToRedirectPDA(raidPtr, pda, 0))
408 goto out; /* no way to verify parity if disk is
409 * dead. return w/ good status */
410 blockNode->succedents[i]->params[0].p = pda;
411 blockNode->succedents[i]->params[2].v = psID;
412 blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
413 }
414
415 RF_ASSERT(!asmap->parityInfo->next);
416 rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
417 RF_ASSERT(asmap->parityInfo->numSector != 0);
418 if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
419 goto out;
420 blockNode->succedents[layoutPtr->numDataCol]->params[0].p = asmap->parityInfo;
421
422 RF_ASSERT(!asmap->qInfo->next);
423 rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
424 RF_ASSERT(asmap->qInfo->numSector != 0);
425 if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
426 goto out;
427 /* if disk is dead, b/c no reconstruction is implemented right now,
428 * the function "rf_TryToRedirectPDA" always return one, which cause
429 * go to out and return w/ good status */
430 blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p = asmap->qInfo;
431
432 /* fire off the DAG */
433 memset((char *) &tracerec, 0, sizeof(tracerec));
434 rd_dag_h->tracerec = &tracerec;
435
436 if (rf_verifyParityDebug) {
437 printf("Parity verify read dag:\n");
438 rf_PrintDAGList(rd_dag_h);
439 }
440 RF_LOCK_MUTEX(mcpair->mutex);
441 mcpair->flag = 0;
442 rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
443 (void *) mcpair);
444 while (!mcpair->flag)
445 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
446 RF_UNLOCK_MUTEX(mcpair->mutex);
447 if (rd_dag_h->status != rf_enable) {
448 RF_ERRORMSG("Unable to verify parity: can't read the stripe\n");
449 retcode = RF_PARITY_COULD_NOT_VERIFY;
450 goto out;
451 }
452 for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
453 rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector);
454 /* the corresponding columes in EvenOdd encoding Matrix for
455 * these p pointers which point to the databuffer in a full
456 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */
457 rf_bxor(p, pbuf, numbytes, NULL);
458 }
459 RF_ASSERT(i == layoutPtr->numDataCol);
460
461 for (i = 0; i < numbytes; i++) {
462 if (pbuf[i] != buf[bytesPerStripe + i]) {
463 if (!correct_it) {
464 RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n",
465 i, (u_char) buf[bytesPerStripe + i], (u_char) pbuf[i]);
466 }
467 }
468 redundantOneErr = 1;
469 break;
470 }
471
472 for (i = 0; i < numbytes; i++) {
473 if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
474 if (!correct_it) {
475 RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n",
476 i, (u_char) buf[bytesPerStripe + numbytes + i], (u_char) redundantbuf2[i]);
477 }
478 redundantTwoErr = 1;
479 break;
480 }
481 }
482 if (redundantOneErr || redundantTwoErr)
483 retcode = RF_PARITY_BAD;
484
485 /* correct the first redundant disk, ie parity if it is error */
486 if (redundantOneErr && correct_it) {
487 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
488 "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY);
489 wrBlock = wr_dag_h->succedents[0];
490 wrUnblock = wrBlock->succedents[0]->succedents[0];
491 wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
492 wrBlock->succedents[0]->params[2].v = psID;
493 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
494 memset((char *) &tracerec, 0, sizeof(tracerec));
495 wr_dag_h->tracerec = &tracerec;
496 if (rf_verifyParityDebug) {
497 printf("Parity verify write dag:\n");
498 rf_PrintDAGList(wr_dag_h);
499 }
500 RF_LOCK_MUTEX(mcpair->mutex);
501 mcpair->flag = 0;
502 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
503 (void *) mcpair);
504 while (!mcpair->flag)
505 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
506 RF_UNLOCK_MUTEX(mcpair->mutex);
507 if (wr_dag_h->status != rf_enable) {
508 RF_ERRORMSG("Unable to correct parity in VerifyParity: can't write the stripe\n");
509 parity_cant_correct = RF_TRUE;
510 } else {
511 parity_corrected = RF_TRUE;
512 }
513 rf_FreeDAG(wr_dag_h);
514 }
515 if (redundantTwoErr && correct_it) {
516 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
517 "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
518 wrBlock = wr_dag_h->succedents[0];
519 wrUnblock = wrBlock->succedents[0]->succedents[0];
520 wrBlock->succedents[0]->params[0].p = asmap->qInfo;
521 wrBlock->succedents[0]->params[2].v = psID;
522 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
523 memset((char *) &tracerec, 0, sizeof(tracerec));
524 wr_dag_h->tracerec = &tracerec;
525 if (rf_verifyParityDebug) {
526 printf("Dag of write new second redundant information in parity verify :\n");
527 rf_PrintDAGList(wr_dag_h);
528 }
529 RF_LOCK_MUTEX(mcpair->mutex);
530 mcpair->flag = 0;
531 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
532 (void *) mcpair);
533 while (!mcpair->flag)
534 RF_WAIT_COND(mcpair->cond, mcpair->mutex);
535 RF_UNLOCK_MUTEX(mcpair->mutex);
536 if (wr_dag_h->status != rf_enable) {
537 RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n");
538 red2_cant_correct = RF_TRUE;
539 } else {
540 red2_corrected = RF_TRUE;
541 }
542 rf_FreeDAG(wr_dag_h);
543 }
544 if ((redundantOneErr && parity_cant_correct) ||
545 (redundantTwoErr && red2_cant_correct))
546 retcode = RF_PARITY_COULD_NOT_CORRECT;
547 if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
548 retcode = RF_PARITY_CORRECTED;
549
550
551 out:
552 rf_FreeAccessStripeMap(asm_h);
553 rf_FreeAllocList(alloclist);
554 rf_FreeDAG(rd_dag_h);
555 rf_FreeMCPair(mcpair);
556 return (retcode);
557 }
558 #endif /* RF_INCLUDE_EVENODD > 0 */
559