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