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