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