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